Focused Agentic Context Toolkit — Spec Kit + RPI for Claude Code
Project description
FACT — Focused Agentic Context Toolkit
A harness that turns Claude Code into an agent that follows Spec Kit + RPI by default, with a local dashboard for progress, tokens, and cost — and a hook-driven audit layer that pauses the workflow on real security / architecture / quality issues (including missing tests) until the human approves.
Status: v0.1 (private repo). Battle-tested on a 46-task greenfield FastAPI project with continuous security & quality audits.
Table of contents
- What is FACT
- Install
- Quickstart
- Dashboard tour
- The workflow
- Audits
- CLI reference
- Slash commands
- Skills shipped with FACT
- Project layout
- Continuity
- Configuration
- Troubleshooting
- Design principles
What is FACT
FACT is the glue between three independent pieces:
- Spec Kit — GitHub's spec-driven development toolkit. Constitution → Spec → Plan → Tasks → Implement.
- RPI (Research-Plan-Implement) — HumanLayer's discipline: stay under the 40% context window, fork context with sub-agents, write semantic summaries at every phase boundary.
- Skills — Anthropic's procedural-knowledge format. FACT ships nine base skills and pulls domain skills from skills.sh on demand for audits.
It runs alongside Claude Code, never wrapping it. Hooks observe the session and feed three things:
- a local dashboard showing the kanban of stories, token cost, and the file tree,
- a session-state file that survives crashes so the agent can resume cleanly tomorrow,
- a hook-driven audit layer that triggers security / architecture / quality reviews via sub-agents loaded with domain skills, and pauses the workflow until the human approves.
Install
Prerequisites
| Tool | Why |
|---|---|
| Python 3.10+ | FACT and its hooks (Claude Code calls FACT's Python helpers directly — no shell required, including on Windows) |
Claude Code on PATH |
the agent harness FACT plugs into |
git |
repo operations + Spec Kit |
gh (only while the repo is private) |
gh auth login is the simplest way to authenticate git for the install |
uv or pipx |
to install FACT in an isolated env |
specify-cli (Spec Kit) is auto-installed on first fact init.
From a fresh machine — macOS
# 1. Homebrew (skip if already installed)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# 2. Prerequisites
brew install python git uv
# Claude Code: download the desktop installer from https://claude.com/claude-code
# 3. Install FACT (pick the line that matches your situation — see below)
uv tool install fact-toolkit # PyPI (once published)
# or, while the repo is private / for unreleased dev builds:
# brew install gh && gh auth login
# uv tool install --from git+https://github.com/holaPymbu/fact.git fact-toolkit
From a fresh machine — Windows (PowerShell)
# 1. Prerequisites via winget
winget install --id Python.Python.3.12 -e
winget install --id Git.Git -e
# Claude Code: download from https://claude.com/claude-code
# 2. uv (recommended over pipx — avoids the broken-launcher problem when Python is upgraded)
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
# >>> Close and reopen PowerShell so PATH refreshes <<<
# 3. Install FACT
uv tool install fact-toolkit # PyPI (once published)
# or, while the repo is private:
# winget install --id GitHub.cli -e ; gh auth login
# uv tool install --from git+https://github.com/holaPymbu/fact.git fact-toolkit
FACT hooks are pure Python — no
bash, no Git Bash on PATH required.
Why not pipx on Windows? pipx installs a
pipx.exeshim hard-coded to one Python install. If you upgrade or reinstall Python the shim breaks withUnable to create process using ...python.exe.uvdoesn't have this problem. If you must use pipx, sidestep the shim:python -m pipx install ....
Already have the prerequisites? Pick one:
Option A — uv tool (recommended)
uv tool install fact-toolkit # PyPI
# or for unreleased dev builds:
uv tool install --from git+https://github.com/holaPymbu/fact.git fact-toolkit
uv handles the isolated environment for you.
Option B — pipx
pipx install fact-toolkit # PyPI
# or:
pipx install git+https://github.com/holaPymbu/fact.git
Option C — clone for development
gh repo clone holaPymbu/fact ~/.fact
python3 -m venv ~/.fact/.venv
~/.fact/.venv/bin/pip install -e ~/.fact
echo "alias fact='~/.fact/.venv/bin/fact'" >> ~/.zshrc
After install, fact --help should work in any directory.
Updating
uv tool upgrade fact-toolkit # Option A
pipx upgrade fact-toolkit # Option B
git -C ~/.fact pull # Option C
After updating FACT itself, run fact upgrade inside any project
to refresh its bundled skills, commands, and hooks.
Maintainers: see CONTRIBUTING.md for the release process (PyPI trusted publishing, version bumps, yanking).
Quickstart
In a new directory (greenfield) or an existing repo (brownfield):
cd my-project/
fact init # one-time setup. Creates .specify/, .claude/, CLAUDE.md.
# Auto-installs specify-cli. Starts the dashboard.
claude # open Claude Code in the same directory
> /fact-start # picks workflow (greenfield/brownfield/demo) and begins
fact init opens the dashboard at http://localhost:7842. Keep
that tab open while you work; it updates in real time as the agent
edits files and tasks close.
Dashboard tour
A single-page local app on port 7842. Four zones, all live:
Header (top)
- Brand —
FACT • <project-name> • <phase>. Phase pill reflects the current Spec Kit phase (constitution,specify,plan,tasks,implement,done). - TASKS —
<done> / <total>aggregated across the visible scope (one feature or all features). - TOKENS — total tokens read from the Claude Code transcript, formatted as K/M. Hover to see the input / output / cache breakdown.
- COST — total session cost in USD, computed from
pricing.json. If a model wasn't priced, it's flagged with?. - SAVED VS OPUS — counterfactual: what the workload would have cost if every sub-agent had been Opus. The bigger this number, the more the Haiku/Sonnet sub-agent strategy is paying off.
Sidebar (left)
- Files tree — every
.mdfile in the project, recursive. Click any to open it in a markdown-rendered modal. Folders are collapsible; defaults expand.specify/,.specify/specs/,.specify/fact/sessions/,.specify/memory/. Ignored automatically:node_modules,.venv,.git,__pycache__,dist,build,*.egg-info, etc. - By model — token spend grouped by model (
opus-4-7,sonnet-4-6,haiku-4-5). Cost + total tokens per model. Hover for the input/output/cache split.
Kanban (center)
Stories go into Pending / In Progress / Done columns. A story is one of:
| Kind | Source | Visual |
|---|---|---|
| foundation | the project's Constitution alone | yellow border, foundation badge |
| workflow | per-feature pre-implement tasks | yellow border, workflow badge |
| user_story | a tasks.md section labeled User Story N, enriched with the title from spec.md |
blue border, US N badge, optional P1/P2/P3 priority pill |
| phase | any other tasks.md section (Setup, Foundational, Polish, …) |
gray border, phase badge |
Each card shows:
- a feature badge (which feature it belongs to, e.g.
001·tea), - the kind badge + optional priority pill,
- a counter pill
done/total, - a slim progress bar (done | in-progress | pending),
- three count pills
✓ N done · ● N in progress · ○ N pending.
Click a card to open the story detail modal — it lists every
task underneath with chips for tags (P, US1, REVIEW, …),
files referenced (clickable, opens the file viewer), and
dependencies (clickable, jumps to that task's detail).
In-progress signal
When the agent is currently working in a story, the card has:
- a pulsing blue glow around the border (CSS keyframes, 2.4s),
- a blinking blue dot next to the kind badge,
- a
started Xm agofooter that updates every 20 seconds.
If a [P] task is delegated to a sub-agent in a worktree, that
specific task pulses violet instead of blue, and the card
shows a ⤵ subagent · model chip indicating which model is
running it.
Toolbar above the kanban
- Search — matches story title or any field of any task in it
(id, title, file, tag, dependency). Tip: press
/from anywhere to focus the search. - Feature picker — switches between features, or
All features(default when there are >1). - Filter dropdown — grouped: story kind (User Story / Phase / Workflow / Foundation), priority (P1 / P2 / P3), and task tag (P, US1, US2, …).
- Hide workflow — toggles foundation + workflow cards off, so you only see real implementation stories.
tags?— opens the tag legend explainingP,US N,REVIEW,BLOCKED, etc.
Footer
A live status line: live · updated HH:MM:SS when the WebSocket
is connected, reconnecting… when it's down. The dashboard
auto-reconnects.
The workflow
FACT is human-in-the-loop by design. The agent never blasts through phases — at every meaningful gate, it stops and asks. Below is the full path from "empty directory" to "feature done", with every user-input gate marked.
flowchart TD
Start(["fact init → claude → /fact-start"]) --> Resume{prior session<br/>state on disk?}
Resume -->|yes| Pick["fact-onboarding asks:<br/>continue or start fresh?"]
Resume -->|no| Type{project type?}
Pick -->|YOU pick| Type
Type -->|Greenfield| Disc["fact-discovery<br/>Socratic Q&A,<br/>one question at a time"]
Type -->|Brownfield| Res["fact-research<br/>7 parallel mappers"]
Type -->|Demo| Tiny["tinyspec extension<br/>skip discovery + clarify"]
Disc -->|YOU shape it| Vision["Vision draft"]
Vision -->|YOU approve, max 2 iterations| Const
Res --> ResMd["research.md"]
ResMd -->|YOU validate| Const
Tiny --> Plan
Const["speckit.constitution"]
Const --> Spec["speckit.specify → spec.md"]
Spec --> Clar["speckit.clarify"]
Clar -->|YOU resolve ambiguities| Plan["speckit.plan → plan.md"]
Plan -->|YOU review the plan| Gate{Pre-implement<br/>audit gate}
Gate -->|critical findings| Plan
Gate -->|clean| Tasks["speckit.tasks → tasks.md"]
Tasks --> Loop["For each task<br/>(see 'Inside the implementation loop' below)"]
Loop --> AuditEdit["per-edit audit<br/>Haiku · security/quality"]
AuditEdit -->|YOU decide on findings| More{more tasks<br/>in user story?}
More -->|yes| Loop
More -->|no| AuditUS["per-user-story audit<br/>Sonnet × 3 · sec/arch/qual"]
AuditUS -->|YOU decide on findings| Next{more user<br/>stories?}
Next -->|yes| Loop
Next -->|no| Done(["Feature done"])
Done -. opt-in .-> FactAudit["/fact-audit all<br/>full review + run test suite"]
classDef user fill:#fff3cd,stroke:#856404,color:#000
classDef gate fill:#f8d7da,stroke:#721c24,color:#000
class Pick,Disc,Vision,Res,ResMd,Clar,Plan,AuditEdit,AuditUS user
class Gate gate
Yellow boxes = your input. Red diamond = blocking gate.
Where you give input
| Stage | What you do |
|---|---|
| Onboarding | Pick greenfield / brownfield / demo. If FACT detects prior session state, also pick: continue or start fresh. |
| Discovery (greenfield) | Answer ~7 topics, one at a time: what to build, who for, what problem, 3-5 v1 features, references, constraints, stack. You can redirect any time ("first tell me about X"). |
| Vision draft (greenfield) | Read the draft and iterate (max 2 rounds). The agent pushes back on scope creep — "is this v1 or are you imagining v2?". |
| Research validation (brownfield) | Read research.md, flag what's missing or wrong. |
| Constitution & spec | Approve / revise the principles + spec the agent produces. |
| Clarify | The agent surfaces ambiguities; you answer them in chat. |
| Plan review | Read plan.md before tasks decomposition. fact-rpi-harness §6 explicitly stops here. |
| Audit gate (pre-implement) | If there are critical findings on the plan, you decide: revise plan, override (with logged reason), or rollback. |
| Per-task audits | After each task, the per-edit audit fires. On findings: fix automatically / fix manually / override / rollback. |
[P] parallel tasks |
Tasks marked [P] in tasks.md are delegated to sub-agents in their own worktrees and reviewed in two stages (spec-compliance → code-quality). On needs_rework, you decide: re-dispatch, fix in main, or accept divergence. |
| End-of-user-story audit | Larger 3-dimension review. Same approval flow. |
| Compaction (60% context) | When context fills, the agent proposes 3 options: /compact, close+reopen, or push through. You pick. |
/fact-audit all |
Anytime, run a full review on demand. |
Inside the implementation loop
The Loop node above is one task. Internally each task can take two
shapes — sequential (the main agent does it) or parallel (a [P]-tagged
task delegated to a sub-agent in a worktree). FACT uses sub-agents in
two distinct ways during implementation:
- Context-forking sub-agents (always available, every task): when the main agent needs to read a lot to act on a little — find call sites, summarize tests, look up library docs — it spawns a short-lived Haiku/Sonnet sub-agent that returns 10-30 lines of distilled findings. The main agent stays focused on the change.
- Task-delegation sub-agents (only for
[P]-tagged tasks): independent tasks that don't share state can run in parallel, each in its own git worktree, each driven by its own sub-agent.
flowchart TD
Task[/Task line in tasks.md/]
Task --> P{"tagged [P]?"}
P -->|no| TddSeq["fact-tdd:<br/>RED → GREEN → REFACTOR"]
TddSeq --> CodeSeq["implement<br/>(forks Haiku/Sonnet sub-agents<br/>for codebase lookups, doc reads,<br/>test summaries while coding)"]
CodeSeq --> VfySeq["fact-verify checklist"]
VfySeq --> Mark["mark x in tasks.md"]
P -->|yes| Spawn["spawn sub-agent<br/>in its own worktree<br/>(model per fact-rpi-harness §3)"]
Spawn --> SubRun["sub-agent runs the task<br/>(applies fact-tdd inside)"]
SubRun --> Stage1["Stage 1 review<br/>Haiku · spec-compliance<br/>against tasks.md + plan.md"]
Stage1 --> Stage2["Stage 2 review<br/>Sonnet · code-quality<br/>diff review"]
Stage2 --> Mark
Mark --> AuditE["per-edit audit<br/>Haiku · security/quality"]
AuditE --> Next([next task])
classDef user fill:#fff3cd,stroke:#856404,color:#000
class VfySeq,Stage1,Stage2,AuditE user
The dashboard surfaces the difference visually: sequential work
pulses blue on the active card; [P] worktree sub-agent work
pulses violet, with a ⤵ subagent · model chip on the card so
you can see which model is doing what.
Cost discipline notes (from fact-rpi-harness §3 and §8):
- Lookup sub-agents: Haiku (~10× cheaper than Opus). Pass
model="haiku"explicitly — without it sub-agents inherit Opus and cost balloons. - Synthesis sub-agents: Sonnet (~5× cheaper than Opus).
- Stage 1 spec-compliance reviews: Haiku (cheap pattern-match).
- Stage 2 code-quality reviews: Sonnet (judgement work).
- The two-stage review typically adds < 5% to total session token cost and catches real bugs the main agent would have merged silently.
The three project types
Greenfield (new project)
The agent loads fact-discovery. You'll have a short, Socratic
conversation — one question per message, with room to redirect. The
topics it needs to leave the conversation having covered:
- What you want to build (one paragraph).
- For whom (target users, not "everyone").
- What problem it solves.
- Scope v1 — 3-5 core features.
- References — projects you admire / want to avoid.
- Constraints — budget, deadline, deployment, language.
- Stack preference (or it suggests after the vision draft).
After every answer, the agent decides: dig deeper, pivot to a topic you opened, or move on. If you say "wait, first I want to talk about X", it follows you. Six exchanges is usually enough.
Then the vision draft, your approval, and Spec Kit:
speckit.constitution → 4-6 principles derived from your vision
speckit.specify → first spec.md
speckit.clarify → ambiguities surfaced; you answer
speckit.plan → tech stack, architecture, code snippets
[ pre-implement audit gate ] ← MANDATORY (see Audits)
speckit.tasks → decompose plan into T-NNN tasks
speckit.implement → write code, task by task
Brownfield (existing repo)
The agent loads fact-research. It spawns 7 parallel sub-agents
(Haiku/Sonnet) that map, in one pass:
- Folder structure
- Stack & dependencies (
pyproject.toml,package.json, etc.) - Code conventions (3-5 representative files)
- Main modules / entry points
- Test framework & coverage shape
- Build & deploy (CI configs, Dockerfile, scripts)
- Existing docs (README, ARCHITECTURE.md, ADRs)
Result: a research.md under 200 lines. You read it and flag what's
missing or wrong. Then constitution + delta spec + plan + audit gate
- tasks + implement, same as greenfield from there.
If the repo already has an AGENTS.md / CLAUDE.md / GEMINI.md,
the agent absorbs its domain knowledge into the constitution and
replaces the old file with a one-paragraph pointer back to
.specify/memory/constitution.md.
Demo (quick experiment)
Uses the tinyspec Spec Kit extension. Skips discovery and clarify
to ship a single throwaway from idea → plan → implement. Useful for
spike work where you don't want the full ceremony.
Session summaries between phases
Between every phase, the agent writes a short summary to
.specify/fact/sessions/<UTC>.md (What was done, What was decided, What's pending / next). These power continuity — if the
session crashes or you close at any point, the next session picks up
from the last summary.
Audits
FACT runs continuous audits driven by hooks. Hooks are pure
triggers — they never run linters or audit logic themselves.
When a hook fires, it emits a structured prompt that pauses the
workflow and instructs the agent to load the fact-audit skill.
The skill then orchestrates the actual review using sub-agents
loaded with domain skills from skills.sh.
Edit / Stop Agent next turn
│ │
▼ ▼
Hook fires ─► emits structured trigger ─► Agent loads fact-audit
+ exits with code 2 │
▼
Spawns sub-agents per
dimension, each loaded
with a domain skill
from skills.sh
│
▼
Aggregates findings,
shows them verbatim
to the user
│
▼
User picks: fix /
manually / override /
rollback
│
▼
Workflow resumes
Three triggers
| Trigger | When | Sub-agent | Dimensions |
|---|---|---|---|
source-edit |
every Edit/Write to .py/.ts/.go/etc |
Haiku | security, quality |
task-close |
edit to tasks.md (likely a task closed) |
Sonnet | security, architecture, quality |
session-stop |
the agent tries to close session | Sonnet (×3 parallel) | security, architecture, quality (+ runs the project test suite separately) |
Tests run via pytest / npm test / cargo test if available.
Test failures count as critical.
User-approval flow
When findings of severity ≥ high exist, the agent shows them
verbatim and offers four options:
- Fix automatically — agent edits the affected files. The next file write re-triggers the audit; it must come back clean for the workflow to resume.
- Fix manually — agent pauses while the human edits.
- Override — agent records the override + the user's reason in the session summary, then continues.
- Rollback — agent proposes the inverse of its last edit; on confirmation, applies it.
Lower-severity findings (medium/low/info) are mentioned in passing without blocking.
Pre-implement gate
Not hook-triggered — explicitly invoked by fact-discovery /
fact-research after /speckit.plan and before /speckit.tasks.
Three Sonnet sub-agents review the plan against constitution +
spec. Critical findings → return to plan iteration.
On demand
> /fact-audit # run all dimensions on full session changes
> /fact-audit security # only that one
> /fact-audit architecture
> /fact-audit quality
Reports
Every audit writes a markdown report to
.specify/fact/audits/<UTC>-<dim>.md with YAML frontmatter
(severity counts, scope, skill used). They surface in the file
tree but not as a dashboard panel — the conversation between
agent and user is the canonical audit surface.
CLI reference
| Command | What it does |
|---|---|
fact init |
Idempotent project setup. Auto-installs specify-cli. |
fact init --port 7900 |
Use a non-default dashboard port. |
fact init --no-dashboard |
Set up the project without starting the dashboard. |
fact init --no-speckit |
Skip the auto-install of specify-cli. |
fact dashboard |
Start (or check) the dashboard server. |
fact dashboard --restart |
Force restart the dashboard. |
fact stop |
Stop the dashboard. |
fact doctor |
Diagnose: what's missing, what's broken. |
fact doctor --fix |
Try to install anything missing (currently: specify-cli). |
fact upgrade |
Re-copy bundled skills / commands / hooks into the project. |
Slash commands
| Command | What it does |
|---|---|
/fact-start |
First time: pick workflow type and begin. Resumed sessions: detects continuity. |
/fact-next |
Continue the current phase or advance to the next. |
/fact-status |
Quick status report in chat (≤10 lines). |
/fact-audit |
Run an audit on demand. Optional arg: security / architecture / quality / all. |
Plus all of Spec Kit's /speckit.* commands (constitution,
specify, clarify, plan, tasks, implement,
verify-tasks, …) which the FACT skills call internally.
Skills shipped with FACT
| Skill | When loaded | What it does |
|---|---|---|
fact-onboarding |
first thing in /fact-start |
Detects continuity, asks for project type, hands off to a workflow skill. |
fact-rpi-harness |
always loaded | The 40% rule, sub-agent strategy, intentional compaction, session summaries. |
fact-discovery |
greenfield workflow | Structured Q&A → vision → constitution → specify → clarify → plan. |
fact-research |
brownfield workflow | Parallel sub-agents map the codebase → research.md → delta spec. |
fact-implement |
implement phase | Per-task discipline: read plan, apply skills, write code, mark done. |
fact-tdd |
by fact-implement for tasks that touch business logic |
RED-GREEN-REFACTOR cycle. Failing test first, smallest code to pass, refactor under green. |
fact-verify |
by fact-implement before flipping [x] on any task |
Verification checklist: tests pass, type-check clean, behavior matches plan, no TODOs / skipped tests left, diff matches files the plan listed. |
fact-skill-installer |
when an external skill is needed | Search skills.sh, present to user, install with explicit confirmation. |
fact-audit |
when a hook trigger arrives | Orchestrates security / architecture / quality reviews; also runs the project test suite as a separate action on session-stop / /fact-audit all. |
Project layout
When FACT manages a project:
my-project/
├── .claude/
│ ├── skills/
│ │ ├── fact-*/SKILL.md (FACT base skills, listed above)
│ │ └── speckit-*/SKILL.md (Spec Kit's own skills)
│ ├── commands/
│ │ ├── fact-start.md
│ │ ├── fact-next.md
│ │ ├── fact-status.md
│ │ └── fact-audit.md
│ ├── hooks/ (pure-Python — Claude Code calls them directly)
│ │ ├── fact_hook.py (FACT observation; tool/session/subagent events)
│ │ ├── fact_audit.py (per-file audit trigger on PostToolUse)
│ │ ├── fact_audit_stop.py (session-stop audit + test-suite runner helper)
│ │ ├── fact_compact_progress.py (60% context-window compaction trigger)
│ │ ├── fact_compact.py (compaction helper, invoked on demand)
│ │ └── fact_session_resume.py (resume nudge on SessionStart)
│ └── settings.json (hook wiring)
├── .specify/
│ ├── memory/
│ │ └── constitution.md (Spec Kit)
│ ├── specs/
│ │ └── <NNN-feature>/ (Spec Kit per-feature)
│ │ ├── spec.md, plan.md, tasks.md, research.md
│ │ ├── checklists/, contracts/, …
│ └── fact/ (FACT operational state)
│ ├── config.json (port, host, agent type)
│ ├── dashboard.pid (running dashboard pid)
│ ├── events.jsonl (append-only hook log)
│ ├── session_state.json (mechanical state)
│ ├── sessions/<UTC>.md (semantic summaries)
│ ├── audits/<UTC>-<dim>.md (audit reports)
│ └── .stop-audit-<id>.fired (loop guard markers)
├── CLAUDE.md (~20 lines, points at skills)
└── (your code: src/, tests/, etc)
Key principle: everything FACT writes lives under
.specify/fact/. There is no parallel ~/.fact/ or ./fact/
directory in the project. If you rm -rf .specify/, you reset
both Spec Kit AND FACT — clean slate.
Continuity
FACT persists state continuously, not at session-close. If you Ctrl+C Claude or the process crashes, the latest snapshot is already on disk. On reopen:
fact-onboardingreadssession_state.jsonfor mechanical state (active task, recent files, model, last update).- It reads the latest
sessions/<UTC>.mdsummary for semantic state (decisions, what was tried, what's next). - It presents a continuity message and asks if you want to continue from where you were.
Three resumption cases handled by the skill:
- Clean close — last task was marked
[x]. Asks: continue with the next pending task? - Mid-task abandon — last task was
[ ]but files were modified. Asks: pick up where I left, or reset and start over? - Corrupt state —
session_state.jsonmissing/garbled. Falls back to the Spec Kit files alone, asks the user what to do.
If both layers are gone (rm -rf .specify/fact/), FACT degrades
to Spec Kit-only — exactly how Spec Kit projects work without FACT.
Configuration
Dashboard port
Default: 7842. Override at init time:
fact init --port 7900
Or edit .specify/fact/config.json:
{
"version": "0.1.0",
"agent": "claude-code",
"dashboard": { "host": "127.0.0.1", "port": 7842 }
}
Pricing
Token costs come from pricing.json shipped with FACT. Verify
against Anthropic's pricing page
at release time; update via fact upgrade when models change.
Hooks
.claude/settings.json is managed by fact init / fact upgrade.
Don't hand-edit unless you know what you're doing — re-running
fact upgrade will preserve your additions but might add FACT
entries again if the markers change.
Troubleshooting
| Problem | Fix |
|---|---|
| Dashboard shows nothing — empty kanban | The agent hasn't run /speckit.tasks yet. Phase cards still appear; T-NNN cards arrive when tasks.md is generated. |
| Dashboard isn't reflecting changes | Hard refresh the browser (Cmd+Shift+R). Cache headers should prevent this but a stale tab can stick. |
specify not found / install failed |
Run fact doctor --fix. If still failing, install manually with uv tool install --from git+https://github.com/github/spec-kit.git specify-cli. |
🔒 FACT AUDIT keeps re-firing on Stop |
Update FACT (fact upgrade). The Stop hook now fires at most once per session. |
Cost shows $0.00 despite agent activity |
The dashboard reads tokens from the Claude Code transcript. Make sure the project was init'd with fact init; then fact upgrade to refresh hook helpers. |
Agent forgot to write active_task_id |
The dashboard infers in-progress from the recent file edit buffer. Should self-correct after the next file edit. |
fact upgrade says nothing changed |
That's fine — it's idempotent. To force a refresh, delete .claude/skills/fact-* and re-run. |
| I want to restart from scratch | fact stop && rm -rf .specify .claude/skills/fact-* .claude/commands/fact-* .claude/hooks && fact init. Your code is untouched. |
Windows: pipx install ... fails with Unable to create process using ...python.exe |
The pipx shim is hard-coded to a Python that no longer exists at that path. Either reinstall pipx (python -m pip install --user --upgrade pipx) or switch to uv (recommended on Windows). |
| Hooks don't fire / dashboard stays empty | Hook commands in .claude/settings.json reference an absolute path to the Python interpreter that ran fact init. If that interpreter has since moved or been uninstalled, the hooks silently fail. Re-run fact upgrade to refresh the paths. |
Claude Code shows Unknown hook event "SubagentEnd" |
Old FACT version. Run fact upgrade inside the project — it renames the event to SubagentStop (Claude Code's current name) and removes the stale entry from settings.json. |
Design principles
These guide every implementation decision in FACT. If a change violates one, the change is wrong, not the principle.
- Single source of truth: Spec Kit
.mdfiles. FACT never writes parallel state files as a substitute. Every derived view (dashboard, status command) reads from the Spec Kit files. - The agent never spends tokens maintaining FACT metadata. What FACT needs to know is deduced from hooks, the filesystem, and the files Spec Kit already generates. Semantic summaries the agent writes are the same it would write under good RPI practice.
CLAUDE.mdis 20 lines or less. Detailed rules live in skills, loaded on demand.- RPI rules are non-negotiable. The 40% smart-zone, intentional compaction, sub-agents for forking context, code snippets in plans — these aren't bendable.
- Sub-agents fork context, not roles. No "frontend agent" or "backend agent". Sub-agents are a compression mechanism.
- Sub-agents use differentiated models. Haiku for lookup, Sonnet for synthesis, the main model for deep reasoning.
- External skills require explicit user confirmation. The agent never downloads a skill without a clear "yes" in chat.
- FACT runs alongside, never in the middle. No wrapping, no proxying.
- Cheap extensibility, not expensive. A single Protocol
(
AgentAdapter), one concrete impl. No plugin registry. - Honest metrics. If a number can't be computed accurately, show a placeholder, never fabricate.
- One project folder. Everything FACT writes is under
.specify/fact/. No parallel root directories. - Continuity is automatic. The user never runs a
pauseorsaveritual. Close anytime, reopen, the agent catches up.
License
MIT.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fact_toolkit-0.3.2.tar.gz.
File metadata
- Download URL: fact_toolkit-0.3.2.tar.gz
- Upload date:
- Size: 273.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5fb85ee236459a2fb62920665393f137454d94021d040f8f6bd7e3154d3c9343
|
|
| MD5 |
a716df430c82d96e602eb78403953f1d
|
|
| BLAKE2b-256 |
f87fb56fd4aeb879299006e2962ae99b25b3945dcaae74d9d0c13a8c45467b09
|
Provenance
The following attestation bundles were made for fact_toolkit-0.3.2.tar.gz:
Publisher:
release.yml on holaPymbu/fact
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fact_toolkit-0.3.2.tar.gz -
Subject digest:
5fb85ee236459a2fb62920665393f137454d94021d040f8f6bd7e3154d3c9343 - Sigstore transparency entry: 1462508782
- Sigstore integration time:
-
Permalink:
holaPymbu/fact@b5f7bd01908faf1de1d315920901e283310af20a -
Branch / Tag:
refs/tags/v0.3.2 - Owner: https://github.com/holaPymbu
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b5f7bd01908faf1de1d315920901e283310af20a -
Trigger Event:
push
-
Statement type:
File details
Details for the file fact_toolkit-0.3.2-py3-none-any.whl.
File metadata
- Download URL: fact_toolkit-0.3.2-py3-none-any.whl
- Upload date:
- Size: 112.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c72ed135def4188dc3b503ea72251111b9ce756c91b257179cd4c8961aa0658b
|
|
| MD5 |
f9018b2864d61cde467417e8f42ac920
|
|
| BLAKE2b-256 |
f6befaf3893a6e4005cb4d225f12570217a049ee2590729f6a9a9e34177f39f3
|
Provenance
The following attestation bundles were made for fact_toolkit-0.3.2-py3-none-any.whl:
Publisher:
release.yml on holaPymbu/fact
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fact_toolkit-0.3.2-py3-none-any.whl -
Subject digest:
c72ed135def4188dc3b503ea72251111b9ce756c91b257179cd4c8961aa0658b - Sigstore transparency entry: 1462508805
- Sigstore integration time:
-
Permalink:
holaPymbu/fact@b5f7bd01908faf1de1d315920901e283310af20a -
Branch / Tag:
refs/tags/v0.3.2 - Owner: https://github.com/holaPymbu
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b5f7bd01908faf1de1d315920901e283310af20a -
Trigger Event:
push
-
Statement type: