Quick Start

Two ways to get Tack running: install the binary (the fast path — no build tools, you just want to use Tack) or run from source in development mode (for contributors and people who want hot reload). Pick the one that matches you.

Prefer pictures? The Step-by-Step Tutorial walks this same page's install → project → tasks → agent-run path once, end to end, with a real screenshot at every step.


Install

Tack is a single self-contained binary — the web UI, REST API, and SQLite engine are all inside one file. No runtime, database server, or container required. Pick any one method.

PlatformInstall → first agent attempt
Linuxmeasured
macOSnot_measured
Windowsnot_measured

One line (Linux / macOS):

curl -fsSL https://raw.githubusercontent.com/yielab/tack/main/install.sh | sh

Verifies the download against that release's SHA256SUMS and refuses to install on a mismatch. Pin a version with TACK_VERSION=v0.1.0-beta.10; choose the install directory with TACK_INSTALL_DIR (default ~/.local/bin).

Homebrew (macOS and Linux):

brew install yielab/tap/tack

Windows:

irm https://raw.githubusercontent.com/yielab/tack/main/install.ps1 | iex

Same TACK_VERSION and TACK_SKIP_CHECKSUM env vars as above, plus TACK_INSTALL_DIR (default %LOCALAPPDATA%\Programs\tack); it verifies SHA256SUMS and adds the install directory to your user PATH — open a new terminal afterwards. Or install with Scoop:

scoop install https://raw.githubusercontent.com/yielab/tack/main/packaging/scoop/tack.json

Or download the .msi from the releases page.

Desktop app. Download it from the releases page — the .AppImage or .deb on Linux, the .msi on Windows, or the .dmg on macOS (built separately for Apple Silicon and Intel). Opening it starts the same server this page describes, inside its own window, with an icon in your system tray: closing the window leaves it running, and the tray's Quit is what actually stops it. If the server it started stops on its own, the tray tells you once — the status line reads "Server stopped" with the exit reason, and reopening the app starts it again; if the app is instead pointed at a server it did not start and that server goes quiet, the tray says so after a few seconds rather than staying silent. Skip to First use once it's open.

Docker: the ghcr.io/yielab/tack image isn't publicly pullable yet — build it yourself from the repo's Dockerfile instead:

git clone https://github.com/yielab/tack.git && cd tack
docker build -t tack:latest .
docker run -d --name tack -p 3210:3210 -v tack-data:/data tack:latest

See Deployment → Docker for the compose file and configuration.

Manual download. Grab the archive for your platform and SHA256SUMS from the releases page, verify, then run:

# Linux / macOS
sha256sum -c --ignore-missing SHA256SUMS   # macOS: shasum -a 256 -c --ignore-missing SHA256SUMS
tar xzf tack-*.tar.gz && cd tack-*/
./tack

On Windows, extract the zip and double-click tack.exe.

From source. No cargo install path exists yet — see Development mode (run from source) below.

First-run note (unsigned binary). The binaries are not code-signed yet. On macOS, right-click → Open the first time (or run xattr -d com.apple.quarantine tack). On Windows, click More info → Run anyway if SmartScreen appears.

Start

tack            # starts the server + web UI at http://localhost:3210

Or start it with the embedded agent runner in one step — see Run an item with an agent below for what that adds:

tack serve --with-runner

Then open http://localhost:3210 in your browser. On first start, Tack creates tack.db and a storage/ folder next to the binary and runs the schema migrations automatically. Those two paths are your data — back them up and you've backed up everything.

Verify the server is up:

curl http://localhost:3210/api/health
# {"status":"ok","version":"0.1.0-beta.7","migrations_applied":62}

migrations_applied is how many migrations this build actually ran — trust that field over any number quoted here; it only grows as the schema does.

If this fails, see Troubleshooting.


First use

  1. Create a project. Click New Project on the Projects page, or press Ctrl+K and type "new project". Choose a project type — a template that pre-loads a matching workflow and vocabulary you can customize later.

  2. Add an item. On the Board, click the + inside any column, or the + New toolbar button. Give it a title and press Enter. An item is the basic unit of work — a task, bug, building, assignment, or whatever your vocabulary calls it.

  3. Move it. Drag the card to another column. Status changes save immediately with optimistic UI (the card moves before the server confirms).

  4. Open the detail drawer. Click the card body (not the drag handle) to see all fields, dependencies, comments, attachments, and custom fields. See Working with Items.

  5. Find your way around. Press Ctrl+K for the command palette (jump to any view, run an action) or Ctrl+/ to search items. Switch theme and palette from the sidebar footer — see Appearance.

Ready to put it on a network or add a token? See Administration & Security.


Run an item with an agent

By default, nothing here executes anything: the server you started above is a full project manager with agent execution off, and clicking an item's Run with agent button shows "Agent execution is off" instead of a form. Run with agent (the button) and --with-runner (a boot flag, further down) are two different things — the button needs some runner active to do anything, and --with-runner is one way to get one. The two paths below are alternatives, not sequential steps: pick the UI path if a server is already running (no restart needed), or the CLI path if you're starting fresh from a terminal.

The UI-first path. Open the Agents page from the sidebar (/agents). Four steps, top to bottom, each one a switch or a form field — no terminal, no id to copy:

  1. "Agent execution on this machine" — click Turn on. This is the one switch ADR 0061 decision 6 exists for: it starts an embedded runner in this same process, on this loopback bind, with no restart and no second binary. (A remote runner on a different machine still needs tack-runner started there — see Enrolling a runner — but nothing on this page requires that.)
  2. "Agents on this machine" — once execution is on, this section reports what it found: codex and/or claude-code, present or not, and whether either one's own vendor login (Claude Max, codex login, ...) already works. Nothing to configure here if a harness is already installed and logged in.
  3. "Vercel AI Gateway key" — paste a gateway key here if you don't want to rely on a harness's own subscription login. It is stored in the runner's own local secret store (the platform keychain where one exists, an owner-only file otherwise) — never in tack.db, never in a log, never echoed back by the API. Saving it immediately re-checks the gateway's model catalog; a real key shows real models below. If execution is already on, saving also restarts the embedded runner with the key, so the next run uses it — no "Re-check" needed in between.
  4. "Default model" — pick a model from that catalog (or from whatever the target harness itself declares) and save it as this project's default. This is what lets the next step submit with zero hand-typed identifiers.

Now open any item and click Run with agent. With a runner active and a default model configured, the dialog's defaults are already correct — confirm and click Run. The item's own Execution tab shows the attempt's state, its requested-vs-actual model, and its usage economics as they land.

The CLI path — scriptable, and what to reach for outside a browser. Every step below is a real command against a real server, copied from an actual run; the fewest steps from the binary you already have to a completed attempt, no second process and no operator-issued token.

Start the server with the embedded runner instead of plain tack (it self-provisions on first start — see Standalone mode; this is the console-command equivalent of step 1 above, not a second thing to do on top of it):

tack serve --with-runner

In another terminal, create an agent profile — its instructions travel with every request created against it:

tack agent-profile create "release-notes" \
  --instructions "Summarize the diff and write docs/CHANGELOG entries."
Created agent profile: release-notes (ap_91b4e)
  id: ap_91b4ea76-9f1a-4725-8a58-21a57d92572c

Find the runner id — the embedded runner enrolled itself under it:

curl -s http://127.0.0.1:3210/api/runners | jq -r '.data[].runner_id'

Using the item id from First use above, create the execution request (swap in your own harness — codex or claude-code — and whichever model it accepts; see Choosing a model and a provider if unsure):

tack execution create <ITEM_ID> \
  --runner <RUNNER_ID> \
  --agent-profile ap_91b4ea76-9f1a-4725-8a58-21a57d92572c \
  --harness claude-code --model-provider anthropic --model-id claude-sonnet-4-5 \
  --agent-profile-snapshot '{"name":"release-notes","instructions":"Summarize the diff and write docs/CHANGELOG entries.","tool_policy":{},"timeout_seconds":600,"budgets":{}}' \
  --repository '{"kind":"git","remote":"/path/to/your/repo","base_revision":"<COMMIT_SHA>","subdirectory":null}' \
  --permission-policy '{"tools":[],"network":false}' \
  --timeout-seconds 600
Created execution request: exec_0fe
  state: queued
  id:    exec_0fe7252989f5f3d40a056c1da45b035039e4a8247ad89e5222cf9280134ec5d1
tack execution get exec_0fe7252989f5f3d40a056c1da45b035039e4a8247ad89e5222cf9280134ec5d1
Execution request exec_0fe7252989f5f3d40a056c1da45b035039e4a8247ad89e5222cf9280134ec5d1
  state:   succeeded (done)

That is a completed attempt, reached either way. See Running an item with an agent for all four ways to create a request and the full field-by-field reference.


Development mode (run from source)

For contributing to Tack or running with hot reload. The API server and Vite dev server run as separate processes.

Prerequisites:

  • Rust toolchain via rustup (stable, 1.94+)
  • Node.js 22+ and npm
rustc --version
node --version

Terminal 1 — API server:

git clone https://github.com/yielab/tack.git
cd tack
cargo run -p tack-cli -- serve

The server binds to http://127.0.0.1:3210 and runs migrations on first start.

Terminal 2 — frontend dev server:

cd frontend
npm install
npm run dev

Vite starts at http://localhost:5173 and proxies all /api/* requests to the API server. Open that URL in a browser.

Build the single binary yourself

One process that serves both the API and the SPA — what the release archives ship:

# 1. Build the frontend
cd frontend && npm run build && cd ..

# 2. Build the API with the embedded SPA
cargo build --release --features embed-spa -p tack-cli

# 3. Run it
./target/release/tack
# open http://127.0.0.1:3210

Without --features embed-spa the binary serves only the API; use the Vite dev server or any static file host for the frontend.


Environment variables

VariableDefaultDescription
TACK_PORT3210Listen port
TACK_DATABASE_URLsqlite:tack.db?mode=rwcSQLite file path
TACK_LOG_LEVELinfotrace · debug · info · warn · error
TACK_API_TOKEN(none)When set, all API calls need Authorization: Bearer <token>

See Configuration for the full reference and tack.toml format, and Administration & Security for tokens, CORS, webhooks, and cloud backup.