how it runs
One daemon, two front-ends
The daemon, kamajid, is the single source of truth. It owns
the SQLite database, the ticket lifecycle, and background session
starts; it serves the browser board and the HTTP/SSE API that both
front-ends use. The kamaji terminal UI is a thin client.
State changes stream to both over Server-Sent Events, so the
board stays in sync no matter where you make a change.
A running daemon listens on three ports:
:8755
the browser Kanban board + the HTTP/SSE API
:8756
the terminal proxy — fronts zellij web for the board's embedded terminals
:8082
upstream zellij web, spawned and managed by the daemon — don't hit it directly
The board address is configurable via
daemon.bind; the
terminal proxy always binds the board port + 1.
run it
Starting kamaji
You don't start the daemon by hand. Both the kamaji
TUI and kamaji ticket create auto-spawn a detached
kamajid if one isn't already healthy (pidfile +
/healthz probe, race-safe), then connect to it.
# the terminal UI — spawns a daemon if none is running $ kamaji # the browser board — same daemon, same data, live terminals $ xdg-open http://127.0.0.1:8755 # seed a Todo ticket without opening the TUI (project inferred from cwd) $ kamaji ticket create --prompt "Fix GitHub issue #123" # …or create it and start its agent immediately, detached $ kamaji ticket create --background --prompt "Fix GitHub issue #123"
Running the daemon standalone
If you only want the browser board (no terminal UI), run the daemon
yourself. In a source checkout, a Makefile wraps the
lifecycle:
$ make start # build kamajid and launch it in the background $ make status # is the daemon responding? (probes :8755/healthz) $ make logs # follow the daemon log (/tmp/kamajid.log) $ make restart # rebuild + relaunch (after pulling new code) $ make stop # stop the running daemon
Equivalently, run the binary directly — the terminal proxy binds the board port + 1:
$ kamajid serve # default bind 127.0.0.1:8755 $ kamajid serve --bind 127.0.0.1:9000 # proxy lands on :9001
Autostart on login (systemd)
Want the board up after every login or reboot? From a source checkout,
install kamajid as a systemd user service. It builds a
release binary into ~/.local/bin, installs a user unit,
and enables lingering so the daemon also starts at boot, before login:
$ make install-service # install + enable + start kamajid.service $ make uninstall-service # stop + remove the unit (binary left in place)
container mode
Sandboxed agents
There are two ways to run kamaji: native — the default, daemon
and agents on your host — and sandboxed, where the daemon,
zellij, and every agent run inside one container so an agent can have
root inside the box without risking your host. Container mode
is opt-in via kamaji up. Rootless Podman
is recommended (container-root maps to your unprivileged user); Docker
also works.
$ kamaji up # run daemon + zellij + agents inside the sandbox $ kamaji status # which mode am I in? + board URL $ kamaji logs # follow container logs $ kamaji down # stop the sandbox — next `kamaji` runs native # tune the sandbox: $ kamaji up --runtime docker --memory 4g --cpus 2 --pids-limit 512
kamaji up reads your registered projects and bind-mounts
each project root (and its worktree dir) at identical paths, mounts your
agent credentials, sets resource limits, and binds the board to the
published port. To add a new project, register it in the browser or TUI,
then re-run kamaji up — it recreates the container to pick
up the new bind-mount; running agent sessions persist via the worktrees
and zellij-cache volume, and resume.
In container mode the browser board is the terminal surface —
open a ticket's inline terminal there. (The TUI's Enter-to-attach opens
a local zellij session, so it isn't used for attaching to in-container
agents in v1.) v1 targets Linux hosts; raw podman/docker
equivalents live in the repo's deploy/ directory.
configure it
Configuration
kamaji reads a single TOML file at
~/.config/kamaji/config.toml (honoring
$XDG_CONFIG_HOME). It's written with sane defaults the
first time kamaji runs, so there's nothing to set up — edit only what
you want to change:
default_agent
which agent new tickets default to — claude, codex, or copilot
worktree_base
where per-ticket git worktrees are created
theme
board colorscheme — also switchable live with t
[daemon]
bind address, log format/level, browser-terminal theme
[auto_review]
auto-move tickets to Review when their agent goes idle
[agents.*]
command templates — bring any agent CLI
Every key, with defaults and gotchas, is documented on the configuration reference page.
restart it
Restarting after config changes
Both kamaji and kamajid read
config.toml once, at startup. The one exception is
theme, which you can switch live from the board with
t. Everything else — [daemon] settings,
[auto_review], agent command templates,
worktree_base — takes effect the next time the daemon
starts. So after editing the file, restart the daemon however you run
it:
# auto-spawned daemon: stop it, then relaunch the TUI (it spawns a fresh one) $ pkill -x kamajid && kamaji # source checkout, daemon standalone: $ make restart # systemd user service: $ systemctl --user restart kamajid # container mode: $ kamaji down && kamaji up
Restarting the daemon is safe for running work: agent sessions live in
zellij, not in the daemon, so they keep running and re-appear on the
board when it comes back. One subtlety:
daemon.web_theme
only applies to zellij sessions created after the restart —
already-running sessions keep their old colors.
stop it
Stopping kamaji
First, know what stops what. Quitting the TUI with q only closes the client — the daemon and every agent session keep running, by design. Detaching from a session with Ctrl+o d leaves the agent working in the background. To actually stop the daemon:
$ make stop # source checkout (pidfile, falls back to pkill) $ pkill -x kamajid # anywhere $ systemctl --user stop kamajid # if installed as a service $ kamaji down # container mode — data preserved
Stopping the daemon does not kill agent sessions — they are
zellij sessions and outlive it. The tidy way to end a ticket's session
is to move the ticket to Done and accept the cleanup prompt
(kills the session, removes the worktree, deletes the branch). Outside
the board, zellij list-sessions and
zellij kill-session <name> work as usual.
Uninstalling
The uninstall script stops a running daemon, removes the
kamaji + kamajid binaries, and removes the
systemd user service if you installed one. Your data — the board
database, config, and cache — is kept by default; add
--purge to delete it too.
# Linux / macOS $ curl -fsSL https://raw.githubusercontent.com/alveflo/kamaji/main/uninstall.sh | sh # …including your data $ curl -fsSL https://raw.githubusercontent.com/alveflo/kamaji/main/uninstall.sh | sh -s -- --purge # Windows (PowerShell) — download first so you can pass -Purge > irm https://raw.githubusercontent.com/alveflo/kamaji/main/uninstall.ps1 | iex
If you installed to a custom location, set the same
KAMAJI_INSTALL_DIR when uninstalling.