Crew is designed to run continuously so its Slack bot, cron jobs, and task runner keep working while you're away from your desk. This page covers the four common deployment patterns.
The simplest path is the built-in installer. It registers a system-level service — systemd on Linux, launchd on macOS — so the gateway survives SSH disconnects, auto-restarts on crash, and auto-starts on boot.
kirocrew service install # registers the unit + starts it kirocrew service status # check running state kirocrew logs -f # tail live logs kirocrew restart # atomic restart (systemd) or unload+load (launchd) kirocrew service uninstall # remove
On Linux the install step prompts for sudo once to write the unit file. The gateway itself runs as your user (User=$USER Group=$(id -gn)), not root. Boot survival is handled by the unit's WantedBy=multi-user.target plus enable --now — nothing extra to configure.
Sudo scope. kirocrew service install only runs sudo tee (to write the unit file under /etc/systemd/system/) and sudo systemctl ... (daemon-reload, enable, restart). No kirocrew, MCP, or LLM code path runs under sudo.
If you'd rather skip the service entirely, tmux survives SSH disconnect but does not auto-restart on crash or auto-start on reboot:
tmux new -s kirocrew kirocrew gateway # Ctrl+B, D to detach # Reconnect with: tmux attach -t kirocrew
For always-on servers — Slack/Discord bots, remote dashboards — the gateway ships as a multi-arch image on GHCR. It's the strongest fit for a headless channel bot that doesn't need a desktop session.
docker run -d --name kirocrew \ -p 127.0.0.1:5476:5476 \ -v kirocrew-home:/home/kirocrew \ ghcr.io/kirodotdev/kirocrew:stable
Or with Docker Compose — copy docker/compose.yaml from the repo and run docker compose up -d.
Two one-time steps after the container is up:
# 1. Log in the agent runtime (survives upgrades — credentials live in the volume) docker exec -it kirocrew kiro-cli login # 2. Mint a dashboard login link (every request requires a token) docker exec kirocrew kirocrew token --ttl 2h
Login links expire minutes after minting — mint, then open immediately. The gateway also prints one link at boot, but by the time you read docker logs it has usually expired, so docker exec minting is the reliable path.
| Tag | Meaning |
|---|---|
stable / latest | Latest stable release (moves on each stable cut) |
insider | Latest insider pre-release |
nightly | Latest nightly build |
0.1.0, 0.1.0-nightly.202607261234 | Exact immutable versions |
linux/amd64 and linux/arm64 are published under every tag. Version tags are never repointed once published — pin a version tag or a digest for reproducible deployments. Every manifest carries SLSA build provenance:
gh attestation verify oci://ghcr.io/kirodotdev/kirocrew:stable --repo kirodotdev/KiroCrew
Channel credentials load from the environment (or from .env in the data home). Pass them with -e or a compose environment: block:
| Variable | Purpose |
|---|---|
SLACK_BOT_TOKEN, SLACK_APP_TOKEN, KIROCREW_OWNER_ID | Slack bot (Socket Mode) |
DISCORD_BOT_TOKEN | Discord bot |
KIROCREW_PORT | Dashboard port (default 5476) |
KIROCREW_BIND | Bind address inside the container (image default 0.0.0.0) |
KIROCREW_ALLOW_UNSANDBOXED | Set 1 to explicitly allow agent exec without the inner sandbox |
On every start the entrypoint moves any channel credentials it finds in the environment into the data home's .env file (mode 600) and removes them from the gateway's environment before the gateway starts — so they never sit in the long-lived process's /proc/<pid>/environ. Environment values win over previously stored ones.
0.0.0.0 inside the container. Outside Docker the gateway binds loopback only. Inside a container, published ports map to the container's bridge interface, so a loopback bind would be unreachable from the host. The image binds all interfaces inside the container's network namespace — nothing is reachable until you publish the port, and -p 127.0.0.1:5476:5476 keeps it host-local./api/health, /api/live, /api/ready), static assets (SPA bootstrap), and local bootstrap endpoints that require a loopback peer plus a filesystem secret.agent.sandbox="auto". If not, agent command execution stays disabled (fail-closed) — the gateway, dashboard, and channel bots run normally. To enable agents without the sandbox, restart with -e KIROCREW_ALLOW_UNSANDBOXED=1.All persistent state — gateway home, kiro-cli credentials, agents, skills — lives under /home/kirocrew in one named volume. Upgrade by pulling a newer image; state carries over:
docker compose pull && docker compose up -d
There is no in-container auto-update. The image is immutable; the tag is the version selector.
Run Crew on an always-on remote Linux host — a VPS, cloud VM, or spare box — so Slack, cron, and the task runner keep working while your laptop sleeps.
slack-mcp.The dashboard binds to localhost:5476 on the remote host. Don't expose that port publicly — forward it to your local machine over SSH:
ssh -L 5476:localhost:5476 user@your-host.example.com
Then open http://localhost:5476 in your local browser.
Make the tunnel automatic on every SSH connection with ~/.ssh/config on your local machine:
Host your-host.example.com LocalForward 5476 localhost:5476
Now ssh your-host.example.com always sets up the tunnel. This works on macOS, Linux, and Windows (OpenSSH is built into Windows 10+).
An ad-hoc SSH tunnel dies when the terminal closes. To keep it running permanently — survives reboots and reconnects on network drops — use a LaunchAgent that supervises a ssh -N process. See the remote-desktop guide in the Crew repo for the exact plist.
When setting up a new remote host, sync your local state so the remote instance has your memories, preferences, lessons, and agent configs from day one.
| Category | Path | Why |
|---|---|---|
| Memory | ~/.kiro/crew/workspace/memory/ | Preferences, projects, history |
| Databases | ~/.kiro/crew/memory.db, .db-wal, .db-shm, memory_index.db | Episodic + semantic (SQLite + WAL for complete state) |
| Config | ~/.kiro/crew/config.json | Settings and model preferences |
| Task specs | ~/.kiro/crew/tasks/ | Saved task-runner specs |
| Skills | ~/.kiro/crew/skills/ | Custom skill definitions |
| Cron jobs | ~/.kiro/crew/crons.json | Scheduled recurring jobs |
Do not sync ~/.kiro/crew/.env, .local_secret, or sel_hmac.key — these are host-specific secrets and are regenerated on first run.
The repo ships a standalone scripts/sync-to-remote.sh that handles atomic SQLite backup, custom port support, session sync for chat history, and remote config patching. Run it from your local machine:
scripts/sync-to-remote.sh user@your-host.example.com scripts/sync-to-remote.sh --dry-run # preview without transferring
Access the dashboard from your phone by exposing the local port through a named HTTPS tunnel and pointing the Slack bot's presigned links at the tunnel URL.
The dashboard binds to localhost:5476 on whichever host runs Crew. A tunneling service — Cloudflare Tunnel, ngrok, or Tailscale Funnel — gives you a stable public HTTPS URL that proxies to that local port. Set the tunnel URL as dashboard.url and the Slack bot generates links your phone can open.
Create a named tunnel that produces a stable URL that doesn't change between restarts. With cloudflared, for example:
# One-time: authenticate and create the named tunnel cloudflared tunnel login cloudflared tunnel create kirocrew # Route a hostname you control to the tunnel, then run it pointed at port 5476 cloudflared tunnel route dns kirocrew kirocrew.example.com cloudflared tunnel --url http://localhost:5476 run kirocrew
Whatever tool you use, the goal is the same: a stable HTTPS URL that proxies to port 5476.
Set dashboard.url in ~/.kiro/crew/config.json:
{ "dashboard": { "url": "https://kirocrew.example.com" } }
Restart the gateway. Then in Slack, type /kirocrew dashboard (or /kirocrew dashboard 6h for a longer session). The bot DMs you a presigned link — tap it on your phone to open the dashboard in your mobile browser.
| Layer | Duration | Notes |
|---|---|---|
| Dashboard token | 1 hour default, up to 20 hours | Configurable via /kirocrew dashboard 6h; practical session limit |
| Presigned link click window | 5 minutes | Must click before it expires |
Most tunnel providers also ship a service installer (cloudflared service install) so the tunnel auto-starts on boot — recommended for 24/7 setups.
kirocrew doctor reports the status of kiro-cli, its authentication, embeddings, Slack tokens, config validity, and MCP servers. Run it any time the gateway looks unhealthy or after a config change.
kirocrew doctor
Running 24/7