Agent onboarding and kf autoconfig

kanban-flow is driven by an agent, so setting a project up means teaching the agent, not only creating directories. Three pieces do that:

Onboarding for a human: kf init

kf init is the human’s way through the same setup. On a terminal it opens with a two-option menu — Quick setup takes the detected defaults, Customize asks each question in turn:

Every question has a default, so Enter accepts it. With no TTY the prompts are skipped and the output says the defaults were used. kf init --defaults takes the defaults even on a terminal — that is the agent’s path — and kf init --minimal scaffolds .works/ and .kf/ without copying the template, hook and review-rule seeds, for a project that wants only the state machine.

What the briefing contains

Four sections, in order:

  1. Project context — the resolved root, the stacks (configured in .kf/config.json, or detected), a one-line config summary (default context, reviewer, agents — the effective values, so a reviewer or agents from ~/.kf/config.json or a workspace .kf/workspace.json shows here; kf config show names each value’s layer) and which agents already have the skills at project scope.
  2. Setup checklist — every setup item, marked done or missing. Each missing item carries the command that fixes it.
  3. Review rules to enforce — the full text of the effective review rules, each labelled with its source. The agent adopts them as coding conventions now, not only when the review phase reads them.
  4. Workflow guide — the pipeline, the three human gates (requirement, plan approval, merging the PR), the in-session task loop and kf verify, and a reminder that every transition is additionally gated on artifacts and report status (kf validate lists what blocks the next move; the full contract lives in gates). It ends with the loop semantics, the --force policy and the commands the agent drives — the command list is generated from the registered CLI help strings, so it cannot drift from the parser.

The checklist, item by item

Check Done means Fix when missing
Project config .kf/config.json exists kf init --defaults (or kf init on a terminal, to answer the onboarding questions)
kf plugin (Claude Code) claude plugin list --json shows kf@kanban-flow installed, enabled and reading this package, at the effective scope (or, when global is missing under a .kf/workspace.json folder, at local scope for that workspace); the line reads - [x] kf plugin (kf@kanban-flow, Claude Code) — installed, enabled (scope: user) (or scope: local), or not installed, installed but disabled, installed … but reading <folder>, not this package. A probe that fails prints ⚠ cannot check kf plugin: <reason> and leaves the item open. Claude Code has no skills or agents row kf install --agent claude --scope <scope> (or --scope workspace for a local workspace install)
Skills, one row per other configured agent The kf-<name> skill copies are linked or copied in that agent’s skills dir at the effective scope (skills.scope, default global); for Antigravity (--agent agy), the bundle lives at ~/.gemini/config/plugins/kf (global) or .agents/plugins/kf (project, or workspace fallback under .kf/workspace.json when global is absent); the label shows the state (missing, partial, stale, broken-link, linked, copied, mixed) kf install --agent <id> --scope <scope> (or kf install --agent agy --scope workspace)
Agents, one row per other configured agent that has an agents dir The 7 agents (code-reviewer, scout, spec-reviewer, developer, test-writer, automation-writer, researcher) are installed in that dir; a file of yours at a managed name shows as foreign kf install --agent <id> --scope <scope>; for foreign, rename your file or keep the substitution
No duplicate project-scope copies Only checked at global scope: no project copy of the skills shadows the global ones kf install (cleans project copies), or kf uninstall --scope project
Base review rules general.md, security.md, performance.md in .kf/review/rules/ kf init --defaults (seeds templates + rules)
Stack rule packs A <stack>.md in .kf/review/rules/ for every stack — config.stacks when set, else detected kf rules --stack <id> (kf rules --list shows packs)
.works/ ignored .gitignore lists .works/ — only checked when .git exists echo '.works/' >> .gitignore
CI a workflow under .github/workflows/ runs validate --all --strict --base add a pull_request step (fetch-depth 0) running kf validate --all --strict --base origin/<base_ref>, so a change without its living-doc update fails
Agent file AGENTS.md or CLAUDE.md at the root create AGENTS.md documenting the commands and conventions
Declared contexts contexts in .kf/config.json optional — kf contexts prints a survey brief for an agent to propose a list, a human confirms it. Without a list, kf new accepts any context
Phase hooks at least one file other than .gitkeep in .kf/hooks/ optional — add shell hooks named after stages (see below)
GitHub link repository in .kf/config.json optional — kf doctor --fix fills it from the GitHub origin remote, or set repository by hand

The checklist reports the current state; it changes nothing itself. Read it as a diff between the project as it is and the project the pipeline expects. kf init also seeds .kf/travel/ into .gitignore (the day files of the travel skill); the checklist does not check it.

Not on the checklist, reported by kf doctor (or kf validate) instead:

Phase hooks

A file named <stage>.sh under a hooks directory runs whenever a transition is about to enter that stage: kf stage runs the destination’s hook, kf archive (and the automatic close after a merge) runs done.sh, kf cancel runs cancelled.sh, and kf new runs brainstorm.sh — deleting the work item it just created when the hook fails. A hook belongs to a transition, so re-running kf archive on an item already in done (a canonical-docs refresh, not a transition) runs no hook. A hook that exits non-zero refuses the transition and prints its output. On kf stage, kf archive and kf cancel a --skip-hooks bypass is available and is recorded in .kfw.json like any other; kf new has no bypass — a failing brainstorm hook simply refuses to create the item.

Resolution order is project .kf/hooks/, then the user’s ~/.kf/hooks/, then the package’s hooks — the first <stage>.sh found wins, so a project hook overrides a user-wide one. The hook runs under bash with the work item’s directory as its working directory and a 120-second timeout, and receives the transition as environment variables:

Variable Value
KFW_FEATURE Work item name
KFW_CONTEXT Its context, empty when none
KFW_FEATURE_DIR The work item’s folder
KFW_WORK_ROOT The project root
KFW_FROM_STAGE The stage being left, empty on kf new
KFW_TO_STAGE The stage being entered
KFW_APPROVAL pending or approved
KFW_REPOSITORY The repository from .kf/config.json (owner/name), empty when none — so hooks never hardcode the repo

Two event hooks sit outside stage transitions and only exist under worktrees:

Hook When it runs Failing means
worktree-create.sh Right after a worktree is provisioned (cwd = the worktree, so npm install, cp .env.example .env, or booting a dev server on $KFW_WORKTREE_PORT happen in the right place). Not on reuse — the environment already exists the worktree (and a freshly created branch) is rolled back and the transition fails, so a retry provisions clean
worktree-remove.sh Right before git worktree remove, still inside the worktree — kill dev servers, docker compose down, release ports a WARNING in the command output; teardown still proceeds

They get the full KFW_* set above plus KFW_EVENT (worktree-create/worktree-remove), KFW_WORKTREE_PATH, KFW_WORKTREE_PORT, KFW_WORKTREE_DOMAIN and KFW_WORKTREE_BRANCH. KFW_WORKTREE_DOMAIN is set only when worktree.domains is on. KFW_FEATURE_DIR still points at the .works/ item folder — only cwd moves into the worktree.

The drive-stop.sh hook was removed together with kf drive; delete it if your project has one.

#!/usr/bin/env bash
# .kf/hooks/testing.sh — refuse to enter testing while the build is red
npm run build || { echo "build fails; fix before testing"; exit 1; }

Hooks are the project’s own gates: anything the built-in gates do not check — a lint run, a migration check, a required label — belongs here rather than in a prompt.

GitHub sync: issue types

The sync hooks create issues; they never create issue types. An issue type (Task, Bug, Feature, or an Epic for an umbrella item) is part of the repository’s GitHub catalog, which GitHub manages at the organization level — there is no kf command for it and the runbook below is run once by a human, with gh authenticated as a repository admin. Every command and its output go into the work item’s testing report, because the catalog is live state that no CI fixture reproduces.

Step Command Expected
1. Read the catalog gh api repos/<owner>/<repo>/issue-types The enabled types; a user-owned repository starts with GitHub’s defaults (Task, Bug, Feature)
2. Create the type gh api --method POST orgs/<org>/issue-types -f name=Epic -f description='Umbrella item' -F is_enabled=true 201 and the type in the catalog on the next step-1 read. Skip when step 1 already lists it
3. Type the issue gh issue edit <n> --type Epic; when the installed gh has no --type flag, the GraphQL mutation updateIssueIssueType(input: {issueId, issueTypeId}) with the ids from steps 1 and gh issue view <n> --json id gh api repos/<owner>/<repo>/issues/<n> --jq .type.name prints Epic
4. Probe the CLI gh issue create --type Epic --title "probe: Epic type" --body "probe", then gh issue close <probe> The probe is created with the type and closed in the same session

When the API refuses. Step 2 has no repository-level form: the only create endpoint is the organization one, so on a repository owned by a user account it answers 404 (or 403 without admin rights). That is a blocker, not a detour — stop, record the exact error, and point the human at the organization settings page where types are managed (https://github.com/organizations/<org>/settings/issue-types; a user account has no such page, so the remaining options are a GitHub-side change or moving the repository under an organization). Leave the tracking issue open and never stand in a label for the type: a label is not read by gh issue create --type, by the board’s type field or by anything that filters on type, so it would pass a glance and fail the acceptance check.

kf autoconfig against kf doctor

Both diagnose the project rather than a work item, and both are read-only. The split is the question asked: autoconfig asks what setup step is missing and answers with a checklist plus fix commands, written for an agent to consume; doctor asks what is broken and answers with a health report that exits 1 on an ERROR. Under global scope inside a workspace folder holding .kf/workspace.json, both kf autoconfig and kf doctor fall back to inspecting workspace-scope installs (<workspace>/.agents/plugins/kf for agy and local scope for claude) when the global install is absent, and kf doctor --fix refreshes stale workspace installs. Run autoconfig once at setup and again after changing .kf/config.json, kf rules or the hooks; run doctor when something stops working.