Agent harnesses¶
fkf harness registers one named base without claiming the global fkf key. Every adapter uses fkf-<base-name>, so independent bases coexist in one user profile and each launch carries an explicit absolute --base.
All ten adapters support read-only MCP. Automatic context hooks are available only for Claude, Codex, Gemini, and Kiro, and only when the caller supplies an explicit workspace. The other adapters remain MCP-only because their current passive hooks either do not consume output or cannot be scoped reliably per base.
Install¶
Inspect one adapter, then install selected names or all adapters:
fkf --base /absolute/path/to/brain harness print codex
fkf --base /absolute/path/to/brain harness install claude codex
fkf --base /absolute/path/to/brain harness install --all
These commands install MCP only. Add automatic context for one canonical workspace explicitly:
fkf --base /absolute/path/to/brain harness print codex --workspace /absolute/path/to/work
fkf --base /absolute/path/to/brain harness install claude codex gemini kiro --workspace /absolute/path/to/work
Preview and check use the same selection:
fkf --base /absolute/path/to/brain harness install --all --dry-run
fkf --base /absolute/path/to/brain harness install --all --check
fkf --base /absolute/path/to/brain status --live
The installer preserves unrelated entries, preflights every target before writing, writes atomically, and saves the immediately previous file as <path>.fkf.bak. Reinstalling the same base and workspace is byte-idempotent. It refuses a scoped key owned by another physical base, an unmanaged command, and overlapping automatic-hook workspaces. A same-named second base must be renamed explicitly in fkf.yaml; FKF does not invent suffixes.
An MCP-only reinstall preserves existing workspace hooks. Changing a hook's workspace checks every other base, including Kiro's separate hook files; base names that share a prefix remain independent.
status --live reports old singleton fkf registrations as manual cleanup candidates. Installation does not delete them.
Both harness print and harness install accept --executable /absolute/path/to/fkf. Use it when package-manager environments put a different FKF version on PATH; the selected persistent launcher is recorded in both MCP and hook configuration. Without this option, FKF resolves the launcher from PATH.
Supported harnesses¶
| Name | MCP configuration | Automatic context with --workspace |
|---|---|---|
claude |
~/.claude.json |
SessionStart |
codex |
~/.codex/config.toml |
SessionStart |
gemini |
~/.gemini/settings.json |
SessionStart |
copilot |
~/.copilot/mcp-config.json |
MCP-only; lifecycle output ignored |
antigravity |
~/.gemini/config/mcp_config.json |
MCP-only; passive output ignored |
opencode |
~/.config/opencode/opencode.json |
MCP-only; no stable passive seam |
grok |
~/.grok/config.toml |
MCP-only; passive output ignored |
cursor |
~/.cursor/mcp.json |
MCP-only; no per-base user hook |
kiro |
~/.kiro/settings/mcp.json, ~/.kiro/hooks/<key>.json |
SessionStart |
cline |
~/.cline/data/settings/cline_mcp_settings.json |
MCP-only; one global hook filename |
No adapter creates a user-scope link to one base's embedded skills. The three skills remain under <base>/.agents/skills/. If a harness needs shared discovery, install a neutral FKF skill separately and require it to select the base by name; it must not infer a base from the skill's own path.
Provider account selection belongs to the process that launches collection. For example, a team collector may export GH_CONFIG_DIR=~/.config/gh-team before fkf sync; ACLI keeps its selected Jira site in its own machine-local configuration. Neither value belongs in fkf.yaml, an MCP registration, or a workspace hook.
Read-only MCP boundary¶
A base named brain registers this shape under fkf-brain:
{
"command": "/absolute/path/to/fkf",
"args": ["mcp", "serve", "--base", "/absolute/path/to/brain"]
}
The server title, instructions, result metadata, resources, and delivery receipts name the selected base. Stored item URIs remain relative JSON values, while model-facing text qualifies citations as fkf://brain/<relative-uri>. The server exposes no sync, body fetch, shell, mutation, or Git audit.
Context-hook boundary¶
The managed hook command pins the FKF executable, physical base, and physical workspace. It checks execution trust before dispatching <base>/sources/fkf-hook.py. The hook accepts only the host event's cwd or workspace field, resolves it physically, and emits nothing unless it is the configured workspace or a descendant. Missing or malformed input, sibling-prefix paths, and symlink escapes produce the host's empty envelope.
On startup it reads yesterday with 600 tokens and repository context with 850 tokens. Claude compact starts skip yesterday and use a 600-token repository reminder. The repository query is the exact repo:github.com/owner/name identity projected from the GitHub origin. Branch names do not become retrieval terms; without a valid repository identity, the hook omits repository context. Every FKF call includes --base; the hook never collects, fetches a body, or uses ambient cwd as session identity.
Each child has a six-second deadline, below the host’s 20-second envelope for the three startup calls. A timeout terminates the child process group, returns the host’s empty envelope, and emits a fixed diagnostic on stderr so delivery failures are observable without leaking child output.
Workspace scope prevents accidental context injection into another checkout. It is not an execution sandbox. Overlapping scopes are rejected because the host cannot reliably distinguish which base should inject context.
Repository tests exercise exact envelopes, the explicit workspace boundary, physical path escapes, closed PATH, pinned executable, repository-name projection, coexistence, conflict handling, rollback, and idempotence. They do not launch a harness; after an upgrade, inspect the harness's own MCP and hook diagnostics.
Collected local metadata¶
When enabled, the bundled agent-sessions.py and agent-memory-files.py collectors read metadata from supported local stores and skip absent products. They never collect prompts or responses.
| Harness | Session metadata store | Memory metadata store |
|---|---|---|
| Claude Code | ~/.claude/projects/<cwd>/*.jsonl |
~/.claude/projects/<cwd>/memory/*.md |
| Codex | ~/.codex/sessions/**/rollout-*.jsonl |
~/.codex/memories/**/*.md |
| Gemini CLI | ~/.gemini/tmp/<project>/chats/session-*.json[l] |
~/.gemini/tmp/<project>/memory/*.md |
| OpenCode | ~/.local/share/opencode/opencode.db |
none |
| Copilot CLI | ~/.copilot/session-store.db |
remote, not collected |
| Antigravity CLI | ~/.gemini/antigravity-cli/history.jsonl |
none |
A session record contains its id, first activity time inside the collected day, harness, working directory, branch, canonical repository identifier when available, and harness-authored title. A file timestamp is never substituted for missing activity evidence.
agent-prompts uses the normalized archive’s immutable generation manifests to exclude transcripts whose high-water mark precedes the requested window. Metadata must match the archive identity and must not predate the transcript; missing metadata takes the bounded full-read path. Enumeration caps at 131,072 generations and 64 MiB of metadata, with at most 8,192 retained transcript candidates. Exact prompt-body reads address the session lineage directly and examine its generations, preserving old bodies as the archive grows. No transcript is deleted by collection.
The separate agent-session-traces source reads only ~/.agents/sessions/v1, the normalized append-only store shared across harnesses. For each newest complete session generation in the requested window it projects bounded user requests, changed paths from git status, verification-looking lines from the last assistant message, harness, and model into ordinary JSON event records. It makes no model call, reads no changed file content, and refuses links in the store. Collection never creates or overwrites tasks/ pages. The personal preset enables this source; the team preset leaves it disabled because session prose may cross a shared-base privacy boundary.
A nightly learning routine belongs to an owner-scheduled agent, not to FKF. That agent may sync, inspect authored task traces, JSON session evidence, and cached memory bodies, and stage .agents/tmp/learn/*.diff; it must stop at fkf learn review <id> --diff until the owner approves or rejects the exact diff.
Use the connection¶
For a coding task, ask the selected MCP server for context with the repository identity and an 850-token budget, then read the cited project decisions when needed. Reuse a relevant startup pack; after compaction, start at 600 tokens. A successful lookup does not require a full configuration read, source sync, task trace, or learning proposal.
Keep shared skills neutral about the selected base. If a retrieval miss is reported, the bundled fkf-use feedback reference turns its query and expected URI into a reviewed case in the existing evaluation file. Registration, a successful protocol call, retrieval acceptance, and improved agent decisions are separate checks.
The passive hook runs with Python 3.9 or newer from the sanitized system PATH. Its syntax stays compatible with that interpreter independently of the FKF package’s Python requirement.
Passive retrieval shares a fifteen-second deadline across Git, day, and repository context calls; each child is capped at ten seconds. A timed-out child group is terminated and the hook reports the bounded fallback without exposing child output.