Installation
giff stack is three independent pieces. Most people only need the CLI. Add the web dashboard and the runner if you want them.
Prerequisites
- Git — any reasonably modern version (≥ 2.30 is fine)
- Rust toolchain — only required for installing the CLI from source. Get it from rustup.rs. Rust 1.75 or newer.
- Node.js — only for running the web dashboard locally. v18+.
- Docker + Docker Compose — only for the optional runner.
- A GitHub personal access token with the
reposcope.
1. The CLI
From crates.io (recommended):
cargo install giffstack
The crate is named giffstack; the binary it installs is called giff
(same convention as ripgrep shipping rg). To upgrade later, re-run
with --force:
cargo install giffstack --force
Or build from a local checkout (good for hacking on it):
git clone https://github.com/nidheesh-m-vakharia/giff.git cd giff cargo install --path crates/giff-cli
Verify:
giff --version giff --help
First-time setup
giff init # writes ~/.config/giff/config.toml skeleton export GITHUB_TOKEN=ghp_xxxxxxxxx # or edit the config and paste it under [github]
The token needs the repo scope. Generate one at github.com/settings/tokens/new?scopes=repo. GITHUB_TOKEN from the env always wins over the value in the config file — useful for keeping the token out of files.
Uninstall
cargo uninstall giffstack
That removes the binary. Per-repo state in .git/stacked.toml and the pre-commit hook stay until you delete them manually.
2. The dashboard (built into the CLI)
No separate install. The SvelteKit dashboard ships embedded inside the
giff binary. Run it from any terminal:
giff dashboard
This starts a tiny HTTP server on a localhost port and opens your default browser:
giff dashboard listening on: → http://local.giffstack.com:51743 (preferred — branded URL via DNS to 127.0.0.1) → http://localhost:51743 (fallback if your DNS blocks the above) opening browser… press Ctrl-C to stop
local.giffstack.com is a public DNS A record that points at
127.0.0.1. The browser does the lookup, hits loopback, and lands on the
local server — traffic never leaves your machine. We use the branded hostname so
cookies and localStorage stay isolated from anything else you have running on
bare localhost.
The same dashboard that runs at giffstack.com runs locally — your GitHub token lives in
localStorage, no data leaves your machine. First run sends you to
/?settings=1; paste your token and pick a repo.
3. Hosting the dashboard yourself (optional)
Same SvelteKit SPA. No backend. Useful if your team wants a shared URL.
cd apps/web npm install npm run dev # http://localhost:5173
For a static deployment:
npm run build # output in apps/web/build/
Serve apps/web/build/ from any static host (Netlify, Vercel, S3, your own nginx). Each visitor pastes their own token; tokens stay in their browser's localStorage.
4. The runner (optional)
A Rust service that polls GitHub, ingests webhooks, retargets PR bases when stacks merge, and (when configured per-repo) auto-merges approved bottom frames.
mkdir -p config cp crates/giff-runner/example-config.toml config/runner.toml # edit config/runner.toml — set [[repos]] slugs, generate webhook_secrets echo 'GITHUB_TOKEN=ghp_xxxxxxx' > .env docker compose up -d curl http://localhost:8080/healthz # → ok
To wire up GitHub webhooks (for instant reactions instead of 15-minute polling), see the runner section in Concepts and the crates/giff-runner/README.md.
Updating
# CLI + embedded dashboard (from crates.io) cargo install giffstack --force # CLI (from a local checkout) cd giff && git pull cargo install --path crates/giff-cli --force # Hosted web dashboard cd apps/web && npm install && npm run build # Runner docker compose pull # once a published image exists docker compose build && docker compose up -d