Development
sh
cargo fmt --check && cargo clippy --all-targets -- -D warnings && cargo test| Tests cover | |
|---|---|
| Parser and conversion | against examples/telegram and examples/whatsapp |
| Share links | visitor isolation, PIN lockout, media allow-list, rooms, auth bypass |
| MCP client | mock servers of every protocol era (HTTP, legacy SSE, stdio) |
| Relay | hub, names, forwarding |
The desktop crate is separate: cd desktop && cargo check.
Layout
src/ server (axum), parsers, LLM agent, MCP client, share links, relay, Telegram
web/ the UI: index.html, app.js, app.css, embedded into the binary
desktop/ Tauri app around the same server
docs/ this site (VitePress)
deploy/ Caddy + Docker Compose
examples/ two fictional exportsDocs
sh
cd docs
npm ci
npm run dev # http://localhost:5173/rooftop/
npm run build # docs/.vitepress/distThe site deploys to irooftop.github.io/rooftop on every push to main that touches docs/. demo.svg is built by python3 scripts/demo-svg.py (plain SVG and CSS, so GitHub renders it).
Releasing
bump Cargo.toml ─▶ tag vX.Y.Z ─┬─▶ Release: crates.io + ghcr.io image (amd64 + arm64, native runners)
└─▶ desktop: installers ─▶ publish release (latest) ─▶ Homebrew: formula + cask- Bump
versioninCargo.toml(anddesktop/), commit, push a tagvX.Y.Z. The tag must be numeric for the Windows MSI. Everything below then runs without further clicks. - Release publishes the crate (secret
CARGO_REGISTRY_TOKEN, environmentcrates-io) and the Docker image: one job per architecture on a native runner (ubuntu-latest,ubuntu-24.04-arm) pushes by digest, and amergejob creates the multi-arch tags. Run it by hand withdry_runto check crate publishing. - desktop builds installers for macOS (arm64, x64), Windows and Linux into a draft release. When all of them are attached, its
publishjob fills in generated release notes, publishes the release and marks it latest. - Its
homebrewjob then calls Homebrew, which pushesFormula/rooftop.rbandCasks/irooftop.rbtoirooftop/homebrew-tap. It needs the secretHOMEBREW_TAP_TOKEN(fine-grained token,irooftop/homebrew-tap, Contents: read and write) orHOMEBREW_TAP_DEPLOY_KEY; without one it skips with a notice. (A release published byGITHUB_TOKENdoes not firerelease: published, which is why the call is explicit; publishing a release by hand still triggers Homebrew through that event.)
Rerun the tap update for an existing tag, for example after adding the secret:
sh
gh workflow run homebrew.yml -f tag=v0.3.0scripts/homebrew-tap.sh vX.Y.Z <tap checkout> renders the same files locally. If the installers of a tag failed, rerun the failed desktop jobs: publish and homebrew follow once they pass.