fapony 0.7.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/README.md +144 -156
  2. package/package.json +5 -6
  3. package/skill/define-convention/SKILL.md +3 -3
  4. package/skill/lookup-before-edit/SKILL.md +2 -1
  5. package/skill/move-to-done/SKILL.md +18 -22
  6. package/skill/plan-with-pony/SKILL.md +4 -4
  7. package/skill/review-pony/SKILL.md +10 -12
  8. package/src/adapters/cli.ts +11 -52
  9. package/src/adapters/hooks/index.ts +0 -67
  10. package/src/adapters/hooks/mv-guard.ts +2 -2
  11. package/src/analyze/discover.ts +1 -1
  12. package/src/analyze/index.ts +0 -1
  13. package/src/commands.ts +8 -39
  14. package/src/core/config.ts +0 -8
  15. package/src/core/fapony-dir.ts +71 -0
  16. package/src/core/hook-helpers.ts +2 -11
  17. package/src/debt/load.ts +3 -5
  18. package/src/debt/promotion.ts +2 -2
  19. package/src/debt/scan.ts +1 -1
  20. package/src/digest/collect.ts +6 -7
  21. package/src/fael.ts +139 -0
  22. package/src/hook.ts +1 -81
  23. package/src/init.ts +30 -90
  24. package/src/install/antigravity.ts +8 -99
  25. package/src/install/claude.ts +66 -200
  26. package/src/install/codex.ts +6 -170
  27. package/src/install/detect.ts +4 -14
  28. package/src/install/opencode.ts +50 -486
  29. package/src/install/types.ts +1 -39
  30. package/src/install/zcode.ts +5 -91
  31. package/src/install.ts +9 -35
  32. package/src/memory.ts +10 -69
  33. package/src/plan/index.ts +34 -0
  34. package/src/plan/next.ts +181 -0
  35. package/src/plan/store.ts +41 -0
  36. package/src/{mem/commands/plan.ts → plan/sweep.ts} +66 -46
  37. package/src/seed/plan-seed.ts +10 -9
  38. package/src/setup.ts +4 -22
  39. package/src/update.ts +1 -1
  40. package/templates/PLAN.md +1 -1
  41. package/src/adapters/hooks/bug-markers.ts +0 -60
  42. package/src/adapters/hooks/context-data.ts +0 -211
  43. package/src/adapters/hooks/edit-hint.ts +0 -215
  44. package/src/adapters/hooks/read-hint.ts +0 -400
  45. package/src/adapters/hooks/session-start.ts +0 -112
  46. package/src/adapters/hooks/stop.ts +0 -768
  47. package/src/adapters/mcp/tools/index.ts +0 -149
  48. package/src/adapters/mcp/tools/mem.ts +0 -258
  49. package/src/adapters/mcp/transport.ts +0 -147
  50. package/src/analyze/cache.ts +0 -162
  51. package/src/core/mem-log.ts +0 -394
  52. package/src/init-mem.ts +0 -143
  53. package/src/install/cursor.ts +0 -167
  54. package/src/install/utils.ts +0 -29
  55. package/src/mem/commands/read.ts +0 -792
  56. package/src/mem/commands/rotate.ts +0 -59
  57. package/src/mem/commands/where.ts +0 -56
  58. package/src/mem/commands/write.ts +0 -284
  59. package/src/mem/engine.ts +0 -329
  60. package/src/mem/index.ts +0 -201
  61. package/src/mem/key-registry.ts +0 -116
  62. package/src/mem/render.ts +0 -66
  63. package/src/mem/selectors.ts +0 -227
  64. package/src/mem/store.ts +0 -356
package/README.md CHANGED
@@ -4,12 +4,85 @@
4
4
 
5
5
  # fapony
6
6
 
7
- [![npm](https://img.shields.io/npm/v/fapony.svg)](https://www.npmjs.com/package/fapony) [![GitHub](https://img.shields.io/github/stars/kire21b/fapony.svg)](https://github.com/kire21b/fapony)
7
+ [![npm](https://img.shields.io/npm/v/fapony.svg)](https://www.npmjs.com/package/fapony) [![GitHub](https://img.shields.io/github/stars/inonix-dev/fapony.svg)](https://github.com/inonix-dev/fapony)
8
8
 
9
- **See what your coding agents actually cost.** fapony reads the session logs Claude Code, Codex,
10
- OpenCode and ZCode already write, and puts them all on one yardstick — tokens, cost and time per
11
- model, per client, per workflow. Nothing to instrument, no per-project setup: it runs on the
12
- history already sitting on your disk.
9
+ **The dev workflow for writing code with agents** — plans cut into one-session chunks, lookups
10
+ that cost a fraction of reading the files, convention debt you can count, and what it all cost in
11
+ tokens. It is one developer's daily flow made into commands; adopting fapony means adopting that
12
+ flow. Memory — decisions, bugs, notes — is [fael](https://github.com/inonix-dev/fael)'s, never
13
+ fapony's.
14
+
15
+ Why chunks: a long plan run in one unbroken session only accumulates context. Every chunk here is
16
+ its own session that opens with just the facts it needs and stops when the chunk lands.
17
+
18
+ ## The workflow — fapony + fael
19
+
20
+ Two tools, one loop, no overlap. **fapony is the workflow** — plans cut into chunks, convention
21
+ debt, cheap lookups, what it all cost. **[fael](https://github.com/inonix-dev/fael) is the memory** — the
22
+ decisions, bugs and notes the next session must see. Each is useful alone; together they close
23
+ the loop: fapony says *what's next*, fael says *what the last session learned*.
24
+
25
+ | | fapony — workflow | fael — memory |
26
+ |---|---|---|
27
+ | Owns | plans + chunk loop, `debt`, `lint-baseline`, `review-seed` / `analyze`, usage | decisions, issues, notes (`add` / `find` / `close`) |
28
+ | Agent surface | plan-mv guard hook, skills — **no MCP server** | MCP tools + SessionStart / read / Stop hooks |
29
+ | Writes | plan files, only when told (`plan sweep --apply`) | its log under `.fael/` in your repo |
30
+ | Install | `npm i -g fapony && fapony install` | `npm i -g @inonix/fael && fael install` |
31
+
32
+ One chunk, one session:
33
+
34
+ ```mermaid
35
+ flowchart TD
36
+ S([new session]) --> K["fael kickoff — SessionStart hook<br/>open decisions + issues"]
37
+ K --> P["fapony plan PLAN-x.md<br/>unchecked chunks + handoff notes from fael"]
38
+ P --> L["fapony review-seed --files …<br/>exports + importers instead of whole-file reads"]
39
+ L --> E["edit<br/>fael read hook: rows about that file"]
40
+ E --> C["tick the chunk with its sha → commit"]
41
+ C --> N["fael add note 'what chunk N+1 must know'<br/>--files f1,f2,PLAN-x.md"]
42
+ N --> X([stop — don't drag the transcript along])
43
+ X -->|next chunk| S
44
+ C -->|last chunk| W["fapony plan sweep PLAN-x.md --apply<br/>git mv into .fapony/done/"]
45
+ ```
46
+
47
+ Who reads what:
48
+
49
+ ```mermaid
50
+ flowchart LR
51
+ CC[Claude Code] --> F[fapony]
52
+ OC[OpenCode] --> F
53
+ ZC[ZCode] --> F
54
+ CX[Codex] --> F
55
+ AG[Antigravity] --> F
56
+ F --> U[usage — tokens & cost]
57
+ F --> P[plans — next chunk, sweep, check]
58
+ F --> D[debt — how far the move has gone]
59
+ M[(fael — memory)] -. read-only .-> F
60
+ CC & OC & CX --> M
61
+ ```
62
+
63
+ fapony is opinionated: the loop above is the product, and the commands exist to make each step
64
+ cheap. Plans and debt are per-project (`fapony init`); usage needs no setup at all.
65
+
66
+ ## The pieces
67
+
68
+ **Plans, one chunk at a time.** `fapony plan` shows every active plan, its progress and next
69
+ unchecked chunk; `fapony plan PLAN-x.md` opens one chunk with just the facts it needs — the
70
+ unchecked boxes, whether the last ticked chunk's commit really exists, and the notes the previous
71
+ session left in fael — instead of dragging the old transcript along.
72
+
73
+ **Lookups instead of whole-file reads.** `fapony review-seed --files <f>` gives exports with line
74
+ numbers and every importer for roughly a thirtieth of the tokens reading those files costs.
75
+
76
+ **Convention debt.** `fapony debt` answers the question nothing else does: *we decided this six
77
+ months ago — how far along is the move?* ESLint says this line is wrong; nothing says 11 of 47
78
+ files have migrated. Dead code and duplication it deliberately leaves to knip and friends —
79
+ they already do that better.
80
+
81
+ ## What it cost — usage
82
+
83
+ fapony reads the session logs Claude Code, Codex, OpenCode and ZCode already write, and puts them
84
+ all on one yardstick — tokens, cost and time per model, per client, per workflow. Nothing to
85
+ instrument: it runs on the history already sitting on your disk.
13
86
 
14
87
  <p align="center">
15
88
  <img src="images/summary.webp" width="800" alt="fapony usage-web summary cards">
@@ -40,47 +113,13 @@ Raw facts from logs are hard to argue with — a vendor can dispute a verdict as
40
113
  dispute their own token count. That is the whole measurement layer: tokens and cost, nothing
41
114
  self-graded.
42
115
 
43
- ## Past day one
44
-
45
- Two more layers, both optional, both compounding:
46
-
47
- **Memory — the mem log.** An agent has no memory of pain across sessions: it writes the 37th
48
- hand-rolled `try/catch` as cheerfully as the first, because every session starts new. Wrappers
49
- and shared libraries get built by *people* who were hurt often enough to remember. fapony
50
- remembers instead: one MCP call per unit of work (`mem_add`) records the decision, bug or note
51
- with the files it touched, and `mem_find` answers *"what was ever decided about this file?"*
52
- before the next agent touches it. The log lives in your repo (`.fapony/.memory/`), so it crosses
53
- machines over git for free.
54
-
55
- **Convention debt.** `fapony debt` answers the question nothing else does: *we decided this six
56
- months ago — how far along is the move?* ESLint says this line is wrong; nothing says 11 of 47
57
- files have migrated. Dead code and duplication it deliberately leaves to knip and friends —
58
- they already do that better.
59
-
60
- ```mermaid
61
- flowchart LR
62
- A[Claude Code] --> F[fapony]
63
- B[OpenCode] --> F
64
- C[ZCode] --> F
65
- D[Codex] --> F
66
- E[Cursor] --> F
67
- G[Antigravity] --> F
68
- F --> U[usage — tokens & cost]
69
- F --> M[mem log — what was decided here]
70
- F --> D[debt — how far the move has gone]
71
- ```
72
-
73
- Adopting it doesn't change your workflow: install it, point your agent at it, read the reports.
74
- Both layers above are per-project (`fapony init`) and worthless on run 1 — they get more useful
75
- every run after, which is exactly why they're retention, not the reason to install.
76
-
77
116
  ## Quick start
78
117
 
79
118
  ```bash
80
119
  # 1. Install (needs Bun — https://bun.sh)
81
120
  npm install -g fapony
82
121
  # from source instead:
83
- # git clone https://github.com/kire21b/fapony.git && cd fapony && bun install && bun link
122
+ # git clone https://github.com/inonix-dev/fapony.git && cd fapony && bun install && bun link
84
123
  # (`bun link` claims the global `fapony` bin by package name, not path — re-run it in the
85
124
  # checkout you want to be the one)
86
125
 
@@ -96,17 +135,16 @@ fapony install --all # skip the prompt, wire everything detected
96
135
  # claude/opencode also symlink skill/<name>/ into ~/.claude/skills — an existing
97
136
  # skill of the same name is reported, never overwritten
98
137
 
99
- # 4. Turn on the memory layer (per project you want it in)
138
+ # 4. Turn on plans + debt (per project you want them in)
100
139
  fapony init /path/to/your-worktree
101
- # creates .fapony/ — .memory/ (the mem log the 3 MCP tools read and write)
140
+ # creates .fapony/ — plan/ done/ spec/, evidence.json for `fapony report`,
102
141
  # and conventions.json for `fapony debt` (shared rules: commit them),
103
- # then offers to write the memory rules into CLAUDE.md / AGENTS.md
104
- # (none yet = AGENTS.md + a CLAUDE.md that imports it) — agents only log
105
- # what the rules they already read tell them to
142
+ # then offers to write the plan-loop rules into CLAUDE.md / AGENTS.md
143
+ # (none yet = AGENTS.md + a CLAUDE.md that imports it)
106
144
  fapony init /path/to/your-worktree --rules --yes # repo already set up: rules only, no prompt
107
- ```
108
145
 
109
- …or add it manually to any MCP client: `{ "mcpServers": { "fapony": { "command": "fapony", "args": ["mcp"] } } }`. Full protocol and adapter examples: [docs/mcp-handcheck.md](https://github.com/kire21b/fapony/blob/main/docs/mcp-handcheck.md).
146
+ # 5. Memory: install fael (npm i -g @inonix/fael && fael install)
147
+ ```
110
148
 
111
149
  ## What fapony is not
112
150
 
@@ -114,69 +152,36 @@ Stated up front, because the gap between these two things is where most tooling
114
152
 
115
153
  - **It does not run your test suite.** The evidence collector runs an allowlist *you* write in
116
154
  `.fapony/evidence.json`, never a command an agent proposes. No allowlist, no evidence.
117
- - **It does not judge your code.** Mem rows *record* what a human or a working agent supplies.
118
- fapony is the memory, not the judge.
155
+ - **It does not judge your code** — and it holds no memory of its own; that is fael's.
119
156
  - **It checks conformance, not correctness** — that a claim lines up with git facts and that
120
157
  uncertainty was declared, not that the code works.
121
- - **Almost nothing blocks.** The one exception is the Stop hook, once per turn when a commit
122
- lands with no new mem row; everything else only annotates.
158
+ - **Almost nothing blocks.** The one exception is the plan-mv guard on Claude Code, which denies a
159
+ raw `git mv` of a plan into done/ and points at `fapony plan sweep --apply`; nothing else touches a
160
+ tool call.
123
161
  - **Model attribution is inferred, not declared** — reports label it `inferred`; read it as such.
124
- - **The knowledge layer is empty on run 1** — worth something around run 5, more every run after.
125
162
 
126
163
  ## What runs where
127
164
 
128
- `fapony install` wires six clients (Claude Code, OpenCode, Cursor, ZCode, Codex, Antigravity). MCP is
129
- the only piece all of them get — the hooks and in-process hints are per-client, and the read/edit
130
- hints arrive **before** the call on Claude Code but **after** it on OpenCode, whose only annotate
131
- channel is `tool.execute.after`. Nothing here is required: skip the hooks and every MCP tool still
132
- answers.
133
-
134
- | | Claude Code | OpenCode | Cursor | ZCode | Codex | Antigravity |
135
- |---|---|---|---|---|---|---|
136
- | MCP tools — `mem_find` `mem_add` `mem_close` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
137
- | Stop hook — refuse to end a turn with commits but no new mem row | ✅ | — | ✅ | — | ✅ after trust | — |
138
- | Read hint — big-file pointer + debt/mem lines | ✅ before | ✅ after | — | — | — | — |
139
- | Re-read hint — unchanged repeat read | ✅ before | ✅ after | — | — | — | — |
140
- | Edit hint — importer count before a shape change | ✅ before | ✅ after | — | — | — | — |
141
- | Commit hint — `git commit` → record-a-mem-row nudge | — | ✅ after | — | — | — | — |
142
- | Skills symlinked into `~/.claude/skills` | ✅ | ✅ | — | — | — | — |
143
- | Skills symlinked into `~/.agents/skills` | — | — | — | ✅ | ✅ | ✅ |
144
- | `usage-scan` reads this client's session log | ✅ | ✅ | — | ✅ | ✅ | — |
145
-
146
- `—` means not wired, not impossible. Codex hooks require trust via `/hooks` before they run —
147
- `fapony install` tells you when. Antigravity gets MCP + skills now; its hook surface is still
148
- evolving, and `usage-scan` can't read its session log yet. The hints live on hooks rather than MCP
149
- on purpose — they must fire mid-turn without the agent deciding to call anything.
150
-
151
- ## The ledger — one habit, 3 tools
152
-
153
- One habit feeds it: record a mem row when a unit of work ends. Everything else on this page is
154
- optional around that. The **Stop hook** is the only thing fapony *blocks* — once per turn, when a
155
- commit lands with no new mem row. It never judges what deserves recording. The hints only
156
- annotate: a big-file read points at `review-seed`, a repeat read of an unchanged file points at
157
- grep, an edit names the file's importer count before you change its shape.
158
-
159
- | Tool | Purpose |
160
- |------|---------|
161
- | `mem_find` | Search the project's mem log read-only — matched on the row's `files[]` (text substring for older rows), `text`, `kind` (no default filter), `since` |
162
- | `mem_add` | Append a mem row (decision/bug/note/next/hold) with `files[]` required and rejected when empty — the write half of `mem_find` |
163
- | `mem_close` | Close a mem row by id with a tombstone message — a separate tool because a close row carries no `files[]` |
164
-
165
- **A tool earns its schema by being called mid-task without being asked.** Everything you invoke
166
- deliberately is a CLI command instead: a tool schema is paid as input tokens in every session of
167
- every client whether or not it is used, while a CLI command costs nothing until it runs. That is
168
- why `stats`, `report`, `usage-web` and friends are CLI-only, and why four tools left the MCP
169
- surface in 2026-09 — the 3 mem tools keep their schemas because nobody is going to type them at
170
- the right moment.
171
-
172
- ## The work side — conveniences, not the contract
173
-
174
- Read-only, deterministic, none of it writes anything. Skip this side entirely and fapony still
175
- works. **Nothing here is a precondition for anything above.**
176
-
177
- - `fapony review-seed --files src/thing/` — exports, importers, untested, for roughly a thirtieth
178
- of the tokens reading those files costs. Before touching an unfamiliar file, fire this and Read
179
- only the line ranges it points at. Directories work too.
165
+ `fapony install` wires five clients (Claude Code, OpenCode, ZCode, Codex, Antigravity) — skills
166
+ everywhere, plus the plan-mv guard on Claude Code. It also removes hooks fapony no longer ships (the
167
+ edit hint, cut 2026-09-26: measured over two windows, it never moved an agent to migrate a file).
168
+ Memory hooks and MCP tools are fael's (`fael install`); fapony has no MCP server.
169
+
170
+ | | Claude Code | OpenCode | ZCode | Codex | Antigravity |
171
+ |---|---|---|---|---|---|
172
+ | Plan-mv guard — deny raw `git mv` of a plan into done/ | ✅ | — | — | — | — |
173
+ | Skills symlinked into `~/.claude/skills` | ✅ | ✅ | — | — | — |
174
+ | Skills symlinked into `~/.agents/skills` | — | — | ✅ | ✅ | ✅ |
175
+ | `usage-scan` reads this client's session log | ✅ | ✅ | ✅ | ✅ | — |
176
+
177
+ `—` means not wired, not impossible.
178
+
179
+ ## Lookups, digest and skills
180
+
181
+ Read-only and deterministic — none of it writes anything.
182
+
183
+ - `fapony review-seed --files src/thing/` — exports, importers, untested. Before touching an
184
+ unfamiliar file, fire this and Read only the line ranges it points at. Directories work too.
180
185
  - `fapony digest` — decisions, open bugs, in-flight plans, cost, on one page, from what's already
181
186
  on disk.
182
187
 
@@ -188,8 +193,8 @@ expects, so a client can symlink the directory rather than copy the file:
188
193
  | Skill | Purpose | Trigger |
189
194
  |-------|---------|---------|
190
195
  | `skill/plan-with-pony/` | Draft plan + spec from "what's in your head" via conversation | `/plan-with-pony` |
191
- | `skill/review-pony/` | Review as verification, wired to fapony: scope facts before (`review-seed`), a mem row after when findings survive | `/review-pony` |
192
- | `skill/lookup-before-edit/` | Look up unfamiliar files (`review-seed --files` + mem + debt) before reading/editing them | `/lookup-before-edit` |
196
+ | `skill/review-pony/` | Review as verification: scope facts before (`review-seed`), a fael row after when findings survive | `/review-pony` |
197
+ | `skill/lookup-before-edit/` | Look up unfamiliar files (`review-seed --files` + fael + debt) before reading/editing them | `/lookup-before-edit` |
193
198
  | `skill/define-convention/` | Turn a not-yet-migrated pattern into a tracked convention (interview + dry-run `debt`) | `/define-convention` |
194
199
  | `skill/move-to-done/` | Archive a shipped PLAN into .fapony/done/ | `/move-to-done` |
195
200
  | `skill/git-commit-conventional/` | Commit split by concern + conventional message | `/git-commit` |
@@ -197,63 +202,59 @@ expects, so a client can symlink the directory rather than copy the file:
197
202
 
198
203
  `plan-with-pony` is vendor-neutral — the SKILL.md *is* the prompt, so pipe it to any agent:
199
204
  `cat skill/plan-with-pony/SKILL.md | claude -p` (or `opencode run`, or anything that reads stdin).
200
- Example plans it produced: [examples/](https://github.com/kire21b/fapony/tree/main/examples).
205
+ Example plans it produced: [examples/](https://github.com/inonix-dev/fapony/tree/main/examples).
201
206
 
202
207
  ### Plans your agent can answer questions about
203
208
 
204
209
  Plans stay markdown files in your repo — nothing moves into a database. Four optional frontmatter
205
210
  keys (`kind` / `status` / `blocked_by` / `blocks`) make a folder of them queryable; plans with no
206
211
  frontmatter still work, because the unchecked checkboxes are enough. Open the next session with
207
- `fapony mem kickoff` — it prints what is next (priority plans, the first unchecked chunk of each,
208
- open bugs) without reading a single 100KB plan body into context:
212
+ `fapony plan` — it prints every active plan with its progress and first unchecked chunk without
213
+ reading a single 100KB plan body into context:
209
214
 
210
215
  ```
211
- ## next up
212
- [1] chunk 2 — move overdue out (PLAN-calendar.md)
213
- [2] bug #mu8t5qve — money drifts in the month grid…
214
- → fapony mem close mu8t5qve "<msg>"
215
- [3] last touched: src/quick/month.tsx, src/lib/money.ts
216
+ # .fapony/plan/ — 3 active plan(s)
217
+
218
+ - PLAN-calendar.md — 1/4 chunks · priority:high
219
+ next: chunk 2 — move overdue out
220
+ - PLAN-billing.md — 0/3 chunks · blocked_by: PLAN-calendar.md
221
+ next: chunk 1 — money type
216
222
  ```
217
223
 
224
+ `fapony plan PLAN-calendar.md` then shows that plan's unchecked chunks, whether the last ticked
225
+ chunk's sha is really in git, and the open fael notes about it — close a chunk with
226
+ `fael add note "<what chunk N+1 must know>" --files <f>,<PLAN path>` and the next session finds it.
227
+
218
228
  **There is no `MASTER.md`** — every line above is derived from the plan files themselves, so it
219
- cannot drift; a hand-kept master file always does. `fapony mem plan-check` verifies ticked chunk
229
+ cannot drift; a hand-kept master file always does. `fapony plan check` verifies ticked chunk
220
230
  shas against git history (a ticked box with no sha to check is a claim, not a close) and flags
221
- dangling `blocked_by` refs; `fapony mem plan-sweep --apply` archives a shipped plan with `git mv`
231
+ dangling `blocked_by` refs; `fapony plan sweep PLAN-x.md --apply` archives a shipped plan with `git mv`
222
232
  into `.fapony/done/` — same name, same depth, so every relative link inside the file survives the
223
233
  move. Specs live in `.fapony/spec/` and are never archived.
224
234
 
225
235
  ## CLI
226
236
 
227
237
  ```bash
228
- # core: memory + debt
229
- fapony mem add <kind> "<text>" --files f1,f2 [--key k] [spec.md] # append a mem row (decision/bug/note/next/hold)
230
- fapony mem close <id> "<msg>" # close a row (a bug stays open without this)
231
- fapony mem find ["<text>"] [--kind a,b] [--files f1,f2] [--since <N>d|YYYY-MM-DD] [--limit n] [--open] # search mem log
232
- fapony mem kickoff [<plan.md>] [--pick <n>] # open a session + a next-up list
233
- fapony mem where # show the resolved mem dir and which step won
234
- fapony mem done | stale | claim | release | synced | plan-sweep | plan-check | rotate
238
+ # core: plans + debt (memory — decisions, bugs, notes — lives in fael)
239
+ fapony plan [<PLAN.md>] # active plans + next chunk; one plan: unchecked chunks + open fael rows
240
+ fapony plan sweep [<PLAN.md>] [--apply] # archive shipped plans into done/ + rewrite links
241
+ fapony plan check [--quiet] # deps, broken links, ticked-chunk shas (exit 1 on issues)
235
242
  fapony debt [--id a,b] [--where <path>] # which files haven't migrated to a declared convention (live, read-only)
236
243
  fapony lint-baseline [--cmd ...] [--diff] # separate "already red" from "I made it red"
237
- fapony init-mem # delete legacy .memory/ dirs + warn call sites still referencing them
238
244
  fapony digest [--since 7d|YYYY-MM-DD] [--format text|html] [--json] [--out FILE] # single-page summary from what's on disk
239
245
 
240
- # usage (day one)
246
+ # usage — what it cost
241
247
  fapony usage-scan # scan session logs → cache (incremental, progress bar)
242
248
  fapony price-scan # fetch model price table → prices.json (cache; query never fetches)
243
249
  fapony usage-web [port] # usage comparison dashboard from cache
244
250
 
245
251
  # lookup (read-only, never touches state)
246
252
  fapony analyze [path] # live repo graph: hubs, orphans, cycles, changed-untested (TS/JS + Python .py/.pyi; stdlib→external, no sys.path)
247
- fapony review-seed [--staged|--commit <sha>|--range <a...b>|--files f1,f2,dir|--plan <PLAN.md>] # scope facts for a review
253
+ fapony review-seed [--staged|--commit <sha>|--range <a...b>|--files f1,f2,dir|--plan <PLAN.md>] [--body sym[,sym]] [--callers sym[,sym]] # scope facts for a review
248
254
  fapony plan-seed <name> [--spec] [--scope <path>[,<path>]]... # write PLAN (+SPEC): frontmatter, capped sections, prior-art list
249
255
 
250
- # hooks & MCP (wired by `fapony install`, not run by hand)
251
- fapony mcp # MCP server (stdio JSON-RPC — 3 tools)
252
- fapony hook-stop # Stop hook: block turns with commits but no mem row
253
- fapony hook-read-hint # read/re-read annotations
254
- fapony hook-edit-hint # importer count before editing shape
256
+ # hooks (wired by `fapony install`, not run by hand)
255
257
  fapony hook-mv-guard # deny raw git mv of plan files into done/
256
- fapony hook-session-start # SessionStart: kickoff into context
257
258
 
258
259
  # frozen ledger (reads history only — the grading tool left the MCP surface in 2026-09)
259
260
  fapony stats [--mode verdict [--regime code|fix|review|plan|inquiry|test]] # KPIs from old graded runs
@@ -261,8 +262,8 @@ fapony report <run-id> # verification report for a run
261
262
  fapony report-web [file] # static HTML report page
262
263
 
263
264
  # setup & maintenance
264
- fapony init <path> # scaffold .fapony/ (plan/spec/memory/evidence)
265
- fapony install [--all|--platform <name>|--dry-run] # wire MCP + skills into clients
265
+ fapony init <path> # scaffold .fapony/ (plan/done/spec/evidence)
266
+ fapony install [--all|--platform <name>|--dry-run] # wire skills + plan-mv guard into clients
266
267
  fapony setup # interactive wizard: config + scaffold in one step
267
268
  fapony update # self-update via git pull
268
269
  fapony telemetry show|send # opt-in only, default off — see TELEMETRY.md
@@ -271,43 +272,30 @@ fapony telemetry show|send # opt-in only, default off — see TE
271
272
  `fapony report <run-id>` prints the full report for a frozen-ledger run — git facts, handoff
272
273
  conformance, allowlisted evidence, the stored verdict, cost — with anything the agent claimed but
273
274
  couldn't prove marked as such. Reports are stamped with the producing build's `server_sha`; after
274
- editing fapony, compare the stamp against `git log -1` before trusting a report from a
275
- long-lived MCP server. Each allowlisted command gets `timeout_ms` (default 30s), the whole report
275
+ editing fapony, compare the stamp against `git log -1` before trusting a report. Each allowlisted command gets `timeout_ms` (default 30s), the whole report
276
276
  capped at 180s — a command that doesn't fit reports as `timeout`, never as a pass. If your
277
277
  `.gitignore` ignores `.fapony/` wholesale, re-include the file: `**/.fapony/*`, then
278
278
  `!**/.fapony/evidence.json`.
279
279
 
280
- *When* to call `mem add` is your project's call, not fapony's — write it in your own
281
- `AGENTS.md`/`CLAUDE.md`. A starting point:
282
-
283
- ```markdown
284
- ## Memory
285
- - Found a bug while working (not just user-reported)? Log it before fixing:
286
- mem_add { kind: "bug", worktree: "<absolute app dir>", files: [...], text: "..." }
287
- - `text` must stand alone — read months later with no chat context: what/where/repro/status.
288
- - Don't fold the fix into the same chunk — log first, fix as its own next/chunk if you do.
289
- ```
290
-
291
280
  ## Config
292
281
 
293
282
  `fapony.config.json` lives in the fapony checkout and is gitignored (it's per-machine). Copy
294
- [fapony.config.example.json](https://github.com/kire21b/fapony/blob/main/fapony.config.example.json)
283
+ [fapony.config.example.json](https://github.com/inonix-dev/fapony/blob/main/fapony.config.example.json)
295
284
  for a complete working reference; every section is optional. Key fields: `worktrees`
296
- (name → path), `memory` (shell commands, or `null` to disable), `paths` / `safety`,
285
+ (name → path), `memory` (shell commands the frozen ledger runs; off unless set), `paths` / `safety`,
297
286
  `usageWeb { port, hostname }`. Env overrides: `FAPONY_CONFIG`, `FAPONY_STATE_DIR` (state DB;
298
- default `~/.config/fapony/`), `FAPONY_NO_REREAD_HINT=1`.
287
+ default `~/.config/fapony/`).
299
288
 
300
289
  ## Scope
301
290
 
302
- **Supported:** MCP server (3 mem tools, any MCP client) · cross-client usage on one yardstick ·
303
- per-project mem log + convention debt · per-client hooks ([matrix above](#what-runs-where)) ·
291
+ **Supported:** cross-client usage on one yardstick · per-project plans + convention debt ·
292
+ per-client hooks ([matrix above](#what-runs-where)) ·
304
293
  vendor-neutral skills (anything that reads stdin) · opt-in telemetry, off by default
305
- ([TELEMETRY.md](https://github.com/kire21b/fapony/blob/main/TELEMETRY.md) lists exactly what
294
+ ([TELEMETRY.md](https://github.com/inonix-dev/fapony/blob/main/TELEMETRY.md) lists exactly what
306
295
  leaves the machine) · Bun-only; run state in SQLite via `bun:sqlite` (WAL mode).
307
296
 
308
- **Not supported (yet):** PreToolUse hints on Cursor, ZCode, Codex or Antigravity — Cursor has no
309
- such hook, the other two expose no in-process hook surface for read/edit hints, and Antigravity's
310
- hook surface is still evolving. A hosted or shared ledger —
297
+ **Not supported (yet):** the plan-mv guard outside Claude Code. Memory of any
298
+ kind — that is [fael](https://github.com/inonix-dev/fael). A hosted or shared ledger —
311
299
  `FAPONY_STATE_DIR` on a synced folder works as an experiment only; SQLite's WAL mode does not
312
300
  tolerate concurrent writers over NFS/Dropbox/iCloud Drive and can corrupt the db under real
313
301
  contention.
package/package.json CHANGED
@@ -1,18 +1,17 @@
1
1
  {
2
2
  "name": "fapony",
3
- "version": "0.7.0",
4
- "description": "Token usage across Claude Code, OpenCode, Codex & ZCode on one yardstick — plus a project mem log and convention-debt tracker agents query via 3 MCP tools. No server, your data stays local",
3
+ "version": "0.7.1",
4
+ "description": "Token usage across Claude Code, OpenCode, Codex & ZCode on one yardstick — plus plans run chunk by chunk and a convention-debt tracker. No server, your data stays local",
5
5
  "license": "MIT",
6
6
  "author": "delamind (https://github.com/kire21b)",
7
- "homepage": "https://github.com/kire21b/fapony#readme",
7
+ "homepage": "https://github.com/inonix-dev/fapony#readme",
8
8
  "repository": {
9
9
  "type": "git",
10
- "url": "git+https://github.com/kire21b/fapony.git"
10
+ "url": "git+https://github.com/inonix-dev/fapony.git"
11
11
  },
12
12
  "keywords": [
13
- "mcp",
14
- "mcp-server",
15
13
  "agent",
14
+ "token-usage",
16
15
  "claude-code",
17
16
  "opencode",
18
17
  "coding-agent"
@@ -8,8 +8,8 @@ description: Turn "files that haven't migrated yet" into a tracked convention
8
8
  One convention = the pattern to use (`ok`) + the pattern meaning not-yet-migrated
9
9
  (`stale`) + scope (`where`) + an optional file condition (`guard`). The output is
10
10
  one row in `<worktree>/.fapony/conventions.json` (`{"conventions": [...]}`), in the
11
- same `.fapony/` dir as the mem log — run `fapony mem where`, go up one level, that
12
- is where the file lives (app-scoped in a monorepo). No file there yet = create it;
11
+ nearest `.fapony/` at or above the code — the same dir `fapony plan` lists plans
12
+ from (app-scoped in a monorepo). No file there yet = create it;
13
13
  a file with rows = append only, never rewrite other rows.
14
14
 
15
15
  ## Phase 1 — One question, then the checker question
@@ -68,7 +68,7 @@ Read it literally — every outcome names its fix:
68
68
  Phase 3.
69
69
  - `0 convention(s)` after `--id` → that id does not exist (misspelling — a dropped
70
70
  row still prints its `⚠`). Only `no conventions.json in <dir>` means you wrote
71
- to the wrong `.fapony/` (re-check `mem where`).
71
+ to the wrong `.fapony/` (the nearest one above the code — `fapony plan` names it).
72
72
 
73
73
  ## Later
74
74
 
@@ -38,7 +38,8 @@ per file, the rest as `(+N)`, so the total is still readable. That is your entry
38
38
 
39
39
  ## History + debt (same paths, two calls)
40
40
 
41
- - `mem_find` with `files: [<same paths>]` — "what was ever decided about this file" (MCP, no CLI spawn).
41
+ - fael `find` with `files: [<same paths>]` (or `fael find --files <paths>`) — "what was ever decided about
42
+ this file". fael already attaches these rows when you Read a file, so call it only for paths you skip reading.
42
43
  - `fapony debt --where <dir|file>` — conventions this path still violates; empty until `conventions.json` exists.
43
44
 
44
45
  ## After the lookup
@@ -37,26 +37,26 @@ You are about to move a PLAN that has been shipped to the archive.
37
37
  A plan that is merely *waiting* (on a person, a customer, a decision) is **not** dead and does
38
38
  not move — mark it `status: blocked` + `blocked_by: <what you are waiting for>` and leave it in
39
39
  `plan/` — the frontmatter is for the next person reading the folder, and the plan stays out
40
- of `done/`, which is what `plan-sweep` and `kickoff` go by. Never `--apply` a blocked file;
40
+ of `done/`, which is what `fapony plan` and `plan sweep` go by. Never `--apply` a blocked file;
41
41
  a blocked file with all chunks ticked is deferred doc debt — ask the user: ship it or keep
42
42
  waiting.
43
43
 
44
- 1c. **Check the dep graph before moving** — `fapony mem plan-check` reads `blocked_by`/`blocks`
44
+ 1c. **Check the dep graph before moving** — `fapony plan check` reads `blocked_by`/`blocks`
45
45
  and says what a human would miss: a `blocked_by` pointing at a file that is not in `plan/`
46
46
  or `done/`, a blocker already in `done/` while the dependent is still `status: blocked`,
47
47
  a waiter cycle, and a blocked plan with all chunks ticked. Fix its issues first — a move
48
48
  on top of a broken graph just relocates the confusion.
49
49
 
50
- 2. **Run `plan-sweep --apply`** — this does the `git mv`, rewrites markdown links inside the
50
+ 2. **Run `fapony plan sweep --apply`** — this does the `git mv`, rewrites markdown links inside the
51
51
  file and inbound links from every `.md` under `.fapony/` (`plan/`, `done/`, `spec/`),
52
52
  warns about plain-text mentions and about tracked files outside `.fapony/` that still
53
53
  name the file, prints a `🔓 <shipped> — <waiter> lists it as blocker` line when the ship
54
54
  unblocks a waiting plan (copy that line into your summary — the waiter keeps
55
- `status: blocked` until its owner clears it), and logs a decision row — all in one call:
55
+ `status: blocked` until its owner clears it) — all in one call:
56
56
  ```bash
57
- fapony mem plan-sweep <PLAN-foo.md> --apply
57
+ fapony plan sweep <PLAN-foo.md> --apply
58
58
  ```
59
- It refuses if the file lacks a shipped header or has open mem rows (next/bug/hold/decision/note).
59
+ It refuses if the file lacks a shipped header or fael still has an open issue about it (notes and decisions travel with the plan).
60
60
  If git refuses ("not under version control" — `.fapony/` is gitignored in this repo), plain
61
61
  `mv` instead; there's nothing to commit for an untracked path, so skip step 4 in that case.
62
62
  The filename gets no date prefix — the ship date is already in the header (step 1).
@@ -71,20 +71,17 @@ You are about to move a PLAN that has been shipped to the archive.
71
71
  chore(plan): archive PLAN-foo.md (shipped <hash>)
72
72
  ```
73
73
 
74
- 5. **Leave a note when the ship taught something** — `plan-sweep --apply` (step 2)
75
- already logged the ship itself as a decision row, so a clean ship needs nothing
76
- more. When the plan hit something a reader could not get from the diff, call the
77
- `mem_add` MCP tool (fapony) once:
74
+ 5. **Leave a note when the ship taught something** — the move itself is in git, so a
75
+ clean ship needs nothing more. When the plan hit something a reader could not get
76
+ from the diff, call fael's `add` tool (or `fael add`) once:
78
77
  - `kind`: `note`
79
78
  - `text`: what the symptom looked like, where the cause actually was, and the
80
79
  rule that follows. Standalone prose — it is read months later with no access
81
80
  to this conversation. Write one only then — "clean ship" files nothing, and a
82
81
  note that repeats the diff teaches the next session nothing
83
82
  - `files`: repo-relative paths this plan touched (`git diff --name-only <base>..HEAD`)
84
- - `spec`: the archived plan's path (post-move, e.g. `.fapony/done/PLAN-foo.md`)
85
- - `worktree`: **absolute path** (`git rev-parse --show-toplevel`) — every other
86
- fapony tool scopes by absolute path too; a bare repo name won't match them
87
- Skip only if fapony's MCP tools aren't available in this session — don't block the archive on it.
83
+ plus the archived plan's path (post-move, e.g. `.fapony/done/PLAN-foo.md`)
84
+ Skip only if fael isn't available in this session — don't block the archive on it.
88
85
 
89
86
  ## Example
90
87
 
@@ -92,25 +89,24 @@ You are about to move a PLAN that has been shipped to the archive.
92
89
  Input: .fapony/plan/PLAN-kickoff.md, no shipped header yet
93
90
  Steps:
94
91
  1. stamp header: > ✅ **shipped 2026-09-13** (a1b2c3)
95
- 2. fapony mem plan-sweep .fapony/plan/PLAN-kickoff.md --apply
96
- → moved, links rewritten, decision logged
92
+ 2. fapony plan sweep .fapony/plan/PLAN-kickoff.md --apply
93
+ → moved, links rewritten
97
94
  3. spec: untouched, stays in .fapony/spec/
98
95
  4. commit
99
- 5. (clean ship — plan-sweep's decision row already recorded it, nothing more to file)
96
+ 5. (clean ship — the move is in git, nothing more to file)
100
97
  ```
101
98
 
102
99
  A ship worth a note looks like this instead:
103
100
 
104
101
  ```
105
- 5. mem_add(kind="note",
102
+ 5. add(kind="note",
106
103
  text="sheet scroll reset on open, not close — the restore hook was on the wrong side; the router's own scrollRestoration resets on every navigate(). Check the router option before writing a restore hook.",
107
- files=["src/routes/expenses/index.tsx"], spec=".fapony/done/PLAN-quick-nav.md",
108
- worktree="/Users/you/Project/vela")
104
+ files=["src/routes/expenses/index.tsx", ".fapony/done/PLAN-quick-nav.md"])
109
105
  ```
110
106
 
111
107
  ## If fail
112
108
 
113
109
  - No git repo / no commits (can't derive a shipped hash) → tell user: "Add header > ✅ **shipped** (<hash>) first"
114
110
  - Stamped the header yourself → always say which hash you used
115
- - plan-sweep refuses (open mem rows) → close them or use `MEM_FORCE=1`
116
- - Too many inbound links → plan-sweep reports them; too many to fix → report the list
111
+ - plan sweep refuses (open fael issue) → fix and `fael close` it, or `MEM_FORCE=1`
112
+ - Too many inbound links → plan sweep reports them; too many to fix → report the list
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: plan-with-pony
3
- description: Draft a plan + spec from "what's in your head" — one question, then a draft you correct. Vendor-neutral — works with Claude Code, OpenCode, Codex, ZCode. Seeds the factual sections from the code and the fapony ledger when the CLI is wired up. Trigger on /plan-with-pony and when the user asks to plan or brainstorm a feature.
3
+ description: Draft a plan + spec from "what's in your head" — one question, then a draft you correct. Vendor-neutral — works with Claude Code, OpenCode, Codex, ZCode. Seeds the factual sections from the code and fael memory when the CLI is wired up. Trigger on /plan-with-pony and when the user asks to plan or brainstorm a feature.
4
4
  ---
5
5
 
6
6
  # plan-with-pony — start from what's in your head
@@ -88,7 +88,7 @@ fapony plan-seed <feature> --spec --scope <path>
88
88
  One command, no MCP round trip. It writes `<planDir>/PLAN-<feature>.md` +
89
89
  `<specDir>/SPEC-<feature>.md` — the frontmatter, the 8 empty sections, a `## 8. References` list
90
90
  of shipped plans that already touched this scope, and a `## Context (fapony)` block under the
91
- TL;DR (recent mem decisions plus what is already in scope — one line per scope file with its
91
+ TL;DR (recent fael decisions plus what is already in scope — one line per scope file with its
92
92
  exports; needs `--scope` to list anything). No ledger-ranking line: the ledger is frozen and
93
93
  cross-model ranking claims are off the table, so the seed does not point at them. SPEC chunks carry
94
94
  verbatim signatures, hard-capped (PLAN ≤ ~60 / SPEC ≤ 200 lines), and capped lines say what was
@@ -149,7 +149,7 @@ normal — writing to the default there scatters plans into a directory nobody r
149
149
  by hand, this check is yours.)
150
150
 
151
151
  **Editing a plan someone is executing right now is a different job from drafting one.** Ask the
152
- dev, or run `fapony mem kickoff` — it reads the same plan files and names the first unchecked
152
+ dev, or run `fapony plan` — it reads the same plan files and names each plan's first unchecked
153
153
  chunk, so a plan already in flight is the one you are about to edit under someone. When that is the case:
154
154
 
155
155
  - **Anything you add is an instruction, not a note.** A measured fact parked under "don't do"
@@ -189,7 +189,7 @@ only place that ordering stays true.
189
189
 
190
190
  **The TL;DR is 15 lines, hard cap, and is the only part that changes while the work is in flight**
191
191
  (tick a box, stamp a short sha). Everything below it is the agreement. A TL;DR allowed to grow
192
- becomes a second copy of the plan, and then neither copy can be trusted. `fapony mem kickoff` reads the
192
+ becomes a second copy of the plan, and then neither copy can be trusted. `fapony plan` reads the
193
193
  checkboxes in the **first `##` section only**, so section 6 stays detail rather than status.
194
194
 
195
195
  Section 6 — every step must be verifiable. Section 8 — must link back to anything it came from. **A step that needs something the system does not store yet** ("the month the accountant has seen",