- Rust 95.3%
- CSS 2%
- Shell 1.3%
- JavaScript 1.3%
| crates | ||
| dist | ||
| docs | ||
| kanabie | ||
| packaging | ||
| scripts | ||
| skills/kanabie | ||
| tests | ||
| .gitattributes | ||
| .gitignore | ||
| .woodpecker.yml | ||
| AGENTS.md | ||
| Cargo.lock | ||
| Cargo.toml | ||
| CLAUDE.md | ||
| install.sh | ||
| Makefile | ||
| README.md | ||
| rust-toolchain.toml | ||
| Taskfile.yml | ||
Kanabie 2
Rust 2024 implementation of the file-based Kanabie worklog. It reads existing trees in place, writes canonical frontmatter, and ships two binaries:
kanabie— CLI, including release-based self-update;kanabie-serve— read-only Axum API and embedded Leptos CSR dashboard.
The current version is 2.13.0.
For task body content, agents and automation should keep generated text out of shell arguments and pass it through stdin instead:
kanabie append 01-01-01-example --stdin
kanabie write 01-01-01-example --stdin
The caller supplies the raw multiline payload on the process stdin stream
(at most 1 MiB). Positional TEXT is intended only as a convenience for short
human-written entries.
To change an existing body, read and send only what is needed:
kanabie read 01-01-01-example --outline # revision + headings with line ranges
kanabie read 01-01-01-example --section Verification
kanabie edit 01-01-01-example --stdin # SEARCH/REPLACE blocks, all or nothing
kanabie append 01-01-01-example --section Verification [--create] --stdin
kanabie write 01-01-01-example --section Scope --stdin
kanabie write 01-01-01-example --if-revision REV --stdin
edit needs no revision: each SEARCH must match the current text exactly once,
so it cannot overwrite a change it did not see. A full or section write takes
the revision printed by read --revision, --outline or --json and refuses a
body that changed since. A change that leaves the body identical writes nothing.
Build and test
Rust 1.94.0 and Trunk 0.21 are expected. Production order matters because the server embeds the completed frontend bundle:
cd crates/kanabie-web && NO_COLOR=false trunk build --release
cd ../.. && cargo build --release -p kanabie-cli -p kanabie-serve
cargo fmt --check
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace
cargo check -p kanabie-web --target wasm32-unknown-unknown
Server
From a repository containing kanabie/:
kanabie-serve
kanabie service install --enable-now
The default bind is 127.0.0.1:8765. Non-loopback binds require allow_remote. The read-only API starts at /api/v1; see API.md.
The dashboard serves these routes:
| Route | Shows |
|---|---|
/ |
Overview: the inbound → local → outbound workflow lanes for the selected repository |
/task/<repo>/<id> |
One task: metadata, gate, links, body |
/report |
History: what changed inside a window, newest first, filterable by any combination of statuses and by tag, and paged. ?all=true drops the window, which is how a tag chip asks for one repository's whole list |
/coverage, /coverage/gaps |
Upstream coverage groups and what is not covered |
/tags |
Tag inventory: the unfinished groups by default, their member counts, roll-up and hygiene advisories |
/tags/<value> |
One group: its members across repositories, in sequence |
/dashboard |
Cross-repository dashboard: repository tiles, an activity chart, closed-coverage, active topics and recent activity |
GET /api/v1/repos/{repo}/tasks remains a published API route with no view of its own: the dashboard retired its separate repository task list once the history view could answer the same question with more control, but a client written against the route is unaffected.
Every route except the two tag views and the dashboard follows the selected repository (?base=). Those three deliberately do not: a cross-cutting tag observed inside a single repository carries no information, and the same is true of the dashboard's chart, coverage figure, topics and recent list, so they cover every configured repository and accept ?base= only as an explicit narrowing.
The history page is labelled History in the navigation, because it is an activity log rather than a status report: a task is on it because it was touched inside the window, whatever its status. It opens on the last 28 days, newest first, 50 rows to a page, and keeps that window, the narrowing, the order and the page in its own URL. The since box takes a plain date and covers that whole day; clearing it returns to the day-count window. Its counts describe every task in the window, not the page below them.
The inventory opens on the groups that still have unfinished members (state=open,stalled), most recently touched first, with the state filter and the order in the URL; the every state link brings the finished ones back. Each row carries the group's last activity and, when a member records one, its last close time — a group where nothing has closed says unknown rather than borrowing modified.
The inventory and the group sequence are computed in kanabie-core and published unchanged by both surfaces — including the filter and the order the dashboard asks for — so kanabie tags [--all-remotes] and /api/v1/tags report the same groups member-for-member, and kanabie list --tag <value> --all-remotes and /api/v1/tags/<value> collect the same members. A group page states how its order was obtained; a group whose members carry no gate/linked edges falls back to close time, then creation, and says so rather than presenting an arbitrary list as a sequence.
Install and systemd user service
For a fresh install, run the one-shot installer. It resolves the latest Forgejo release, downloads the musl archive and SHA256SUMS, verifies the checksum, and installs both binaries:
curl -fsSL https://git.chaos-it.pl/b.zablocki/kanabie2/raw/branch/main/install.sh | sh
The same installer supports offline or pinned-release installation when the archive and checksum file are already present:
./install.sh kanabie-2.13.0-x86_64-unknown-linux-musl.tar.gz SHA256SUMS
kanabie service install --root /path/to/worklog
For a project bound to a detached worklog, pass the project directory as --root; the service then resolves the binding at startup like the CLI does.
The installer verifies the checksum, preflights both executables, atomically replaces each destination and creates the compatibility symlink kanabie_serve. A direct one-shot or archive installation leaves the existing service state unchanged and does not create or enable a missing service. Pass --enable-now explicitly to kanabie service install when that is intended.
Existing installations use the same installer engine through the CLI:
kanabie update --check
kanabie update
update checks the latest public Forgejo release, downloads the complete archive and checksum, and replaces kanabie plus the sibling kanabie-serve only after verification. It refuses to overwrite a binary inside a Git checkout unless --force is passed. --target KANABIE_PATH selects a different CLI path and --url RELEASE_API_URL selects another compatible latest-release endpoint. Before a real update it records whether kanabie-serve.service is active and restarts it after successful installation only in that case. It never enables, disables or starts an inactive service; --check and no-op updates do not touch systemd.
Install or refresh the bundled Kanabie skill in every active agent environment with:
kanabie skill install
Kanabie currently detects Claude from CLAUDE_CONFIG_DIR or an existing ~/.claude directory, and Codex from CODEX_HOME or an existing ~/.codex directory. It installs into each detected skills/kanabie directory without creating an otherwise inactive environment. Use repeatable --environment claude or --environment codex arguments to select targets explicitly; an explicit target may be created even when that environment has not been initialized yet.
kanabie skill update is the same refresh restricted to environments that already have skills/kanabie. A detected environment without it is left untouched and only receives an install recommendation on stderr, and detecting no environment at all is reported on stderr instead of failing. The installer runs it after every successful bundle replacement — through the newly installed executable, so refreshed skill files always match the installed binary — and reports a failing refresh on stderr without failing the installation. Set KANABIE_REFRESH_SKILLS=0 to skip that step. kanabie update --check reports the same skill state without writing anything.
An identical service install is idempotent. Kanabie records checksums in $XDG_CONFIG_HOME/kanabie/service-state.toml; a changed config or unit is not overwritten or removed unless --force is given:
kanabie service install --root /path/to/worklog --force
kanabie service uninstall --disable-now
kanabie service uninstall --disable-now --force # remove locally modified managed files
Taskfile workflows
Task v3 can drive the common local build and release workflows:
task build
task reinstall
task release VERSION=v2.13.0
task release -- VERSION=v2.13.0
build creates the Trunk bundle before compiling the native release binaries. reinstall builds the current workspace version, installs its verified archive into ~/.local/bin, and restarts kanabie-serve.service only when it is already active.
release is the publishing workflow and must start from a clean, fully committed main. It checks that local main contains origin/main and that the target tag is unused, updates all version-bearing files when needed, runs the complete local quality/release gate plus an installer smoke test, creates a release: prepare kanabie X.Y.Z commit when it changed the version, creates the annotated vX.Y.Z tag, and pushes main followed by the tag. The Woodpecker tag pipeline publishes the Forgejo release and verifies the downloaded artifacts. A failure before the release commit restores the automatic version edits; a push failure leaves the verified local commit/tag available for a safe retry.
task release returns after pushing main and the tag; it does not wait for Woodpecker or poll the public release. Treat publication as complete only after both the push and tag pipelines succeed and the published archive plus SHA256SUMS pass an independent download check. A pushed tag without a corresponding tag pipeline is a webhook/CI failure that still needs diagnosis.
Release gate
Official archives target only x86_64-unknown-linux-musl. Set the version explicitly; the build has no stale fallback version:
cargo audit
systemd-analyze verify packaging/kanabie-serve.service
VERSION=2.13.0 ./scripts/build-release.sh
The archive in dist-release/ contains both binaries, the installer, README, API and frontmatter docs, the Kanabie skill and the systemd unit. Packaging is reproducible for a fixed SOURCE_DATE_EPOCH. Tag CI uses only forgejo_release_token, then downloads the published archive and checksum and smoke-tests the downloaded server.
Unknown metadata and bodies are preserved, block/inline lists are read, mixed extensions remain per-file, and mutations use a process lock plus atomic replace. Gates are written with task gate/task ungate; --status deferred queries gated tasks. See FRONTMATTER.md.