running kamaji

Run it. Configure it. Stop it.

kamaji is one background daemon — kamajid — with two front-ends: a terminal UI and a browser board. You almost never manage the daemon by hand, but everything below is there when you want to.

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.

~/code/acme-api
# 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:

~/code/kamaji
$ 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
$ 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:

~/code/kamaji
$ 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.

container mode
$ 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:

restart kamajid
# 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:

stop kamajid
$ 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.

uninstall
# 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.