@balacode/mental 0.2.0

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 (53) hide show
  1. package/.claude-plugin/marketplace.json +17 -0
  2. package/.claude-plugin/plugin.json +22 -0
  3. package/.cursor-plugin/plugin.json +21 -0
  4. package/.mcp.json +8 -0
  5. package/CHANGELOG.md +42 -0
  6. package/LICENSE +21 -0
  7. package/README.md +277 -0
  8. package/assets/logo.svg +19 -0
  9. package/bin/cli.mjs +135 -0
  10. package/bin/commands/attention.mjs +139 -0
  11. package/bin/commands/decide.mjs +104 -0
  12. package/bin/commands/doctor.mjs +150 -0
  13. package/bin/commands/heartbeat.mjs +21 -0
  14. package/bin/commands/hooks.mjs +41 -0
  15. package/bin/commands/install.mjs +86 -0
  16. package/bin/commands/journal.mjs +54 -0
  17. package/bin/commands/link.mjs +18 -0
  18. package/bin/commands/list.mjs +51 -0
  19. package/bin/commands/local.mjs +118 -0
  20. package/bin/commands/note.mjs +61 -0
  21. package/bin/commands/reindex.mjs +48 -0
  22. package/bin/commands/remap.mjs +76 -0
  23. package/bin/commands/search.mjs +55 -0
  24. package/bin/commands/serve.mjs +16 -0
  25. package/bin/commands/show.mjs +61 -0
  26. package/bin/commands/split.mjs +56 -0
  27. package/bin/commands/status.mjs +136 -0
  28. package/bin/commands/uninstall.mjs +58 -0
  29. package/bin/commands/where.mjs +29 -0
  30. package/bin/lib/args.mjs +117 -0
  31. package/bin/lib/bindings.mjs +404 -0
  32. package/bin/lib/entry.mjs +35 -0
  33. package/bin/lib/git.mjs +149 -0
  34. package/bin/lib/heartbeat.mjs +118 -0
  35. package/bin/lib/hooks.mjs +144 -0
  36. package/bin/lib/ignore.mjs +122 -0
  37. package/bin/lib/import-legacy.mjs +183 -0
  38. package/bin/lib/index.mjs +574 -0
  39. package/bin/lib/install-cli.mjs +100 -0
  40. package/bin/lib/install-skills.mjs +120 -0
  41. package/bin/lib/mcp.mjs +389 -0
  42. package/bin/lib/okf.mjs +746 -0
  43. package/bin/lib/output.mjs +112 -0
  44. package/bin/lib/pkg.mjs +22 -0
  45. package/bin/lib/resolve.mjs +302 -0
  46. package/bin/lib/uninstall.mjs +56 -0
  47. package/hooks/session-start.sh +4 -0
  48. package/mcp.json +11 -0
  49. package/package.json +43 -0
  50. package/plugin.json +21 -0
  51. package/rules/mental.mdc +18 -0
  52. package/skills/mental/SKILL.md +277 -0
  53. package/skills/mental/references/templates.md +186 -0
@@ -0,0 +1,277 @@
1
+ ---
2
+ name: mental
3
+ description: >-
4
+ Maintains a project-continuity log via the Mental CLI. Reconstructs where
5
+ work stands from git, the latest journal handoff, open decisions, and
6
+ attention residue; records why consequential decisions were made; extracts
7
+ residue from a meeting dump or plan-progress question; and leaves an exact
8
+ resume point after substantive work. Use when starting or finishing
9
+ non-trivial repository work, answering project-orientation questions,
10
+ ingesting a transcript into residue (never storing the transcript), or
11
+ recording a decision that git cannot explain.
12
+ license: MIT
13
+ compatibility: Requires Node.js >=18 and git. Bundled MCP launches ./bin/cli.mjs serve.
14
+ metadata:
15
+ author: Ali Farahat
16
+ version: "1.0.0"
17
+ tags: continuity,journal,decisions,orientation,handoff
18
+ user-invocable: true
19
+ disable-model-invocation: false
20
+ when_to_use: |
21
+ USE WHEN:
22
+ - You begin substantive work in a repository.
23
+ - The user asks any orientation question: "where are we with this project?",
24
+ "where did I leave off?", "what's remaining?", "what did I decide about X?",
25
+ "what did I get done last week?", "what was that plan / where did I get?".
26
+ - The user pastes a meeting transcript or asks "what do I have to get done
27
+ from this?"
28
+ - The user states a concern, "Tom said X", or "park this for later".
29
+ - A substantive task reaches a verified handoff point.
30
+ - A consequential decision is made, deferred, or awaiting user input.
31
+ - Mid-task: you are about to change an approach, residue surfaces, or other
32
+ agents may have written since you oriented.
33
+
34
+ DO NOT USE WHEN:
35
+ - The turn is trivial or read-only and does not ask for project orientation.
36
+ - The information is already obvious from code, git, or canonical docs.
37
+ - The information is cross-repository, personal, or secret.
38
+ ---
39
+
40
+ # Mental — project continuity (CLI-first)
41
+
42
+ > **Leading words:** derive, do not maintain; task boundary; exact handoff;
43
+ > decisions explain git; CLI is the write path; optional, never required.
44
+
45
+ Mental exists to make a later human or agent session continue without
46
+ reconstructing intent from chat history. Git records what changed. Mental
47
+ records the small amount git cannot explain: current focus, consequential
48
+ decisions and their rationale, durable repository-specific knowledge, attention
49
+ residue still in the air after a hop, and the next exact action.
50
+
51
+ Write for the user returning in two weeks. Be concise, factual, and explicit
52
+ about observed versus inferred information.
53
+
54
+ **OKF markdown is the source of truth.** Agents must call the CLI with `--json`.
55
+ Do not grep `.mental`, `~/.mental`, or YAML frontmatter. Humans on a TTY can run `mental` with no args for a one-shot heartbeat (resume, last outcome, git, residue, open decisions). Agents use `mental heartbeat --json` for the same cheap pulse — not `status` unless they need notes.
56
+
57
+ ## Non-goals
58
+
59
+ - Not a task manager, GTD app, chat transcript store, analytics store, or
60
+ replacement for repository documentation. Never clone a meeting into 40
61
+ todos. Never duplicate a plan file into Mental.
62
+ - Not a place to duplicate code, README content, git history, or issue trackers.
63
+ - Not a secret store. Never write credentials, tokens, private keys, or sensitive
64
+ user data.
65
+ - Not a dependency. Work must continue when Mental is absent, stale, or
66
+ unavailable (fail open).
67
+
68
+ ## Commands (always `--json`)
69
+
70
+ ```text
71
+ mental where --json
72
+ mental heartbeat --json
73
+ mental status --json
74
+ mental search "…" --json
75
+ mental list --type Decision --json
76
+ mental show <path> --json
77
+ mental journal --title "…" --body "…" --resume "…" --against PLAN.md --json
78
+ mental attention --title "…" --kind direction --status open --json
79
+ mental decide --title "…" --status open --json
80
+ mental decide --title "…" --status decided --json
81
+ mental note --title "…" --json
82
+ ```
83
+
84
+ ## Mental receipt (end of turn)
85
+
86
+ If you invoked `mental` this turn, end the **user-visible** reply with this block.
87
+ Last thing in the message. Not a code fence (so emojis render).
88
+ Skip the whole block if you did not run `mental`.
89
+
90
+ Separator is a literal `<br>` on its own line (not dashes, not a blank line).
91
+ Next line is the title `🧠 Mental`. Then one item line per thing that happened,
92
+ type-emoji first. At most four item lines; if more, keep the writes and end
93
+ with `+N more`.
94
+
95
+ Titles only — no `file://` or markdown links. Mental files live in `~/.mental`,
96
+ not this repo, so links would 404. The CLI tool card already has the path.
97
+
98
+ **Writes (copy this shape):**
99
+
100
+ ```text
101
+ <br>
102
+ 🧠 Mental
103
+ 📓 journaled “Resolver landed”
104
+ 🚦 recorded attention “Tom said ship”
105
+ 🎯 decided “Keep the JSON envelope”
106
+ ```
107
+
108
+ **Read-only (heartbeat / search / show / list):**
109
+
110
+ ```text
111
+ <br>
112
+ 🧠 Mental
113
+ 🔍 heartbeat
114
+ ```
115
+
116
+ | Emoji | Kind | Item line |
117
+ | --- | --- | --- |
118
+ | 📓 | Journal | `📓 journaled “<title>”` |
119
+ | 🚦 | Attention | `🚦 recorded attention “<title>”` or `🚦 resolved attention “<title>”` |
120
+ | 🎯 | Decision | `🎯 decided “<title>”` or `🎯 opened decision “<title>”` |
121
+ | 📝 | Note | `📝 noted “<title>”` |
122
+ | 🔍 | Read | `🔍 heartbeat` / `🔍 searched` / `🔍 showed` / `🔍 listed` |
123
+
124
+ Mix writes and a read in one block if both happened. Never invent Mental activity.
125
+
126
+ If `mental` is not on PATH, try `npx @balacode/mental …`. If that fails, continue
127
+ the user's coding task and mention `npm i -g @balacode/mental` then `mental install`.
128
+
129
+ `where` reports `{ root, id, mode, reason, gitRoot }` and may include `imported`
130
+ and `indexed` when a leftover project `./.mental/` was ingested into the home
131
+ UUID slice. Modes: `env` (MENTAL_DIR), `local` (`./.mental/` after `mental local`),
132
+ `home` (`~/.mental/projects/<uuid>/`), `personal` (`~/.mental` when cwd is not a
133
+ git repo). Never overlay personal + project trees.
134
+
135
+ Leftover `./.mental` without the `.mental-local` marker is **normalized** into
136
+ `~/.mental/projects/<uuid>/` on first **write** (`install` / `status` / `journal`,
137
+ not `where`) (canonical paths + frontmatter) and indexed in sqlite. The leftover
138
+ folder stays on disk; writes go to the home slice. Identity is a UUID in
139
+ `~/.mental/bindings.json`, not a path and not git origin.
140
+
141
+ Templates (humans / rare manual repair only): [references/templates.md](references/templates.md).
142
+
143
+ ## Lifecycle
144
+
145
+ ### 1. Orient
146
+
147
+ Before substantive work:
148
+
149
+ ```text
150
+ mental where --json
151
+ mental heartbeat --json
152
+ ```
153
+
154
+ `heartbeat` is the cheap reload (resume, last outcome, git, residue, unsettled
155
+ decisions). Use `mental status --json` when you also need notes. `status`
156
+ refreshes `status/current.md` as a disposable cache — not SoT. Never block
157
+ work if Mental errors; mention it and continue.
158
+
159
+ ### 2. Record selectively
160
+
161
+ Create a decision only when a choice changes the project's direction, constrains
162
+ future work, or is explicitly deferred:
163
+
164
+ - `open`: options require a user decision.
165
+ - `deferred`: intentionally parked; state what it awaits.
166
+ - `decided`: record what was chosen, why, and when.
167
+ - `superseded`: preserve the file and link the replacement.
168
+
169
+ ```text
170
+ mental decide --title "…" --status open --json
171
+ mental decide --title "…" --status decided --json
172
+ ```
173
+
174
+ Same `--title` updates the existing file (paths are identities). `--path` targets a specific file.
175
+
176
+ **Attention (residue), not journal, not note.** Use when something occupies
177
+ working memory after a hop but is not a choice-fork and not a durable fact:
178
+
179
+ - `kind: direction` — "Tom said X" (optional `--from Tom`)
180
+ - `kind: concern` — a worry that would cost a reload if forgotten
181
+ - `kind: thread` — an unfinished thread of attention
182
+ - `status: open` | `later` | `resolved` — **must resolve**; residue that cannot
183
+ close is a graveyard. Cap ≤7 on the heartbeat. Merge duplicates.
184
+
185
+ ```text
186
+ mental attention --title "…" --kind direction --status open --from "Tom" --json
187
+ mental attention --title "…" --status resolved --json
188
+ ```
189
+
190
+ Create a note only for a durable, non-obvious, repository-specific fact likely
191
+ to save future investigation. If deleting the note would not cost future time,
192
+ do not write it. Never use `note` for meeting leftovers.
193
+
194
+ ```text
195
+ mental note --title "…" --json
196
+ ```
197
+
198
+ **Transcript / meeting dump:** extract residue (and 0–2 real decisions). Never
199
+ store the transcript in OKF. Never clone 40 todos. If more than 7 items would
200
+ cost a reload, keep the 7 costliest-to-forget; the rest stay in the source.
201
+
202
+ **Plan-progress questions** ("what was that plan / where did I get / what's
203
+ left?"): `mental heartbeat --json` (or `status --json`) + read `against` + the
204
+ plan file in the repo. Answer from pointer + last handoff + open attention.
205
+ Do not copy the plan into Mental.
206
+
207
+ ### Mid-chat re-entry (between orient and close)
208
+
209
+ Mental is not only a start/finish ritual. Step back in cheaply whenever:
210
+
211
+ - **Structured lookup** — open decisions, residue of a kind, a status:
212
+ `mental list --type Decision --status open --json` (or `--kind direction`).
213
+ Do not search and do not grep YAML for field filters.
214
+ - **Approach change** — before abandoning or switching an approach,
215
+ `mental search "…" --json` then `mental show <path> --json` for the hit
216
+ (backlinks are on `show`). Also `mental list --type Decision --json`.
217
+ If the switch constrains the future, record it with `mental decide` at once.
218
+ - **Residue surfaces** — "Tom said X", a worry, "park this": record
219
+ `mental attention` **now**, not at handoff. Chat memory fades; the OKF file
220
+ does not.
221
+ - **Parallel agents** — other sessions share the same home slice. If time
222
+ passed or another agent may have written, re-pulse `mental heartbeat --json`
223
+ before acting on stale assumptions. It derives git live and costs little.
224
+ - **"Why is it like this?"** — `mental search "…" --json`, then `show` the
225
+ path; a decision or note may already hold the answer. Follow `backlinks`
226
+ instead of grepping.
227
+
228
+ Reads are always safe. Writes stay selective: mid-chat re-entry does not change
229
+ what deserves a decision, attention item, or note.
230
+
231
+ ### 3. Close at a deterministic task boundary
232
+
233
+ A task boundary occurs when any of these is true:
234
+
235
+ - A substantive implementation or investigation has been verified and is ready
236
+ for final handoff.
237
+ - The user changes topic, pauses, or explicitly asks to stop.
238
+ - A consequential decision is made or deliberately deferred.
239
+
240
+ At the boundary, append **one** journal section (not one per chat turn). If
241
+ work was against a plan file, pass `--against`:
242
+
243
+ ```text
244
+ mental journal --title "<outcome>" --body "<what changed; evidence; only what git cannot explain>" --resume "<one exact next action> — open loops: <none or list>" --against PLAN.md --json
245
+ mental heartbeat --json
246
+ ```
247
+
248
+ Skip trivial or read-only turns.
249
+
250
+ ## Orientation responses
251
+
252
+ When asked where work stands, run `mental heartbeat --json` (add `status --json`
253
+ if notes matter) and answer from that evidence:
254
+
255
+ - Current branch and worktree state
256
+ - Latest completed outcome
257
+ - Plan pointer (`against`) when set — then read that file; do not invent a backlog
258
+ - Residue still in the air (open / later attention)
259
+ - Open or deferred decisions
260
+ - Active notes (only from `status`)
261
+ - Exact resume action
262
+
263
+ Separate observed facts from inference. Do not recite the entire journal.
264
+
265
+ ## Privacy and safety
266
+
267
+ - Default store is `~/.mental` (private). Project `./.mental/` exists only after
268
+ the user runs `mental local`.
269
+ - Never stage, commit, publish, attach, or quote Mental contents in PRs, issues,
270
+ release notes, code comments, or external messages.
271
+ - Never store secrets.
272
+ - Never edit `.gitignore`, `.git/info/exclude`, or global git configuration.
273
+ Tell the user to run `mental doctor` (or `mental doctor --fix-ignore`).
274
+ - If creating `./.mental/` and `git check-ignore` fails, refuse and point at
275
+ `mental doctor --fix-ignore`.
276
+ - Never delete existing concepts without explicit user approval.
277
+ - Uninstall must not delete OKF; that requires a typed confirmation the CLI owns.
@@ -0,0 +1,186 @@
1
+ # `.mental/` file templates
2
+
3
+ Minimal templates for project continuity. Substitute `<...>` placeholders.
4
+ `type` is required; `timestamp` is the last-updated time in ISO-8601. Use links
5
+ relative to the file containing them.
6
+
7
+ Agents must not fill these by hand-editing YAML. Run `mental journal`,
8
+ `mental attention`, `mental decide`, `mental note`, and `mental status` (with `--json`).
9
+
10
+ ## Bundle skeleton
11
+
12
+ ```text
13
+ .mental/ # project-local (only after `mental local`)
14
+ # or ~/.mental/projects/<uuid>/
15
+ ├── index.md
16
+ ├── status/current.md
17
+ ├── decisions/
18
+ ├── attention/
19
+ ├── journal/
20
+ └── notes/
21
+ ```
22
+
23
+ Create `index.md` and `status/current.md` from the templates below; leave the
24
+ other directories empty until meaningful concepts exist. Existing optional
25
+ directories from earlier versions remain valid user data; never delete them
26
+ automatically.
27
+
28
+ ## `index.md` (bundle entry point)
29
+
30
+ ```markdown
31
+ ---
32
+ type: Status
33
+ title: <Project> — .mental index
34
+ description: Entry point and navigation for this repo's .mental bundle.
35
+ tags: [index]
36
+ timestamp: <ISO-8601>
37
+ status: active
38
+ ---
39
+
40
+ # <Project> — mental index
41
+
42
+ Private continuity log for <repo>. Start at
43
+ [current status](status/current.md).
44
+
45
+ - [Status](status/current.md) — disposable snapshot derived from live evidence
46
+ - [Journal](journal/) — concise outcomes and exact handoffs
47
+ - [Decisions](decisions/) — consequential choices and rationale
48
+ - [Attention](attention/) — residue still in the air after a hop
49
+ - [Notes](notes/) — durable facts that prevent repeat investigation
50
+ ```
51
+
52
+ ## `status/current.md`
53
+
54
+ ```markdown
55
+ ---
56
+ type: Status
57
+ title: Current status
58
+ description: Derived "you are here" snapshot — regenerate, don't hand-edit.
59
+ tags: [status]
60
+ timestamp: <ISO-8601>
61
+ status: active
62
+ ---
63
+
64
+ # Status — <project>
65
+ _Derived <date> from journal tail + git + residue + decisions + notes. Stale? Re-derive._
66
+
67
+ ## Now
68
+ <current focus, one or two factual sentences>
69
+
70
+ ## In flight
71
+ <branch, PR, and uncommitted work observed in git; write "None" when clean>
72
+
73
+ Against <PLAN.md>
74
+
75
+ ## In the air
76
+ - [<title>](../attention/<file>.md) — direction
77
+ - [<title>](../attention/<file>.md) — later
78
+ - None
79
+
80
+ ## Unsettled
81
+ - [<title>](../decisions/<file>.md) — open
82
+ - [<title>](../decisions/<file>.md) — deferred: <what it awaits>
83
+
84
+ ## Notes
85
+ - [<title>](../notes/<slug>.md) — <one-line fact>
86
+ - None
87
+
88
+ ## ▶ Resume point
89
+ <one exact next action copied from the latest journal Resume line>
90
+ ```
91
+
92
+ ## `journal/<YYYY-MM-DD>.md`
93
+
94
+ ```markdown
95
+ ---
96
+ type: Journal
97
+ title: Journal — <YYYY-MM-DD>
98
+ description: Work log for <YYYY-MM-DD>.
99
+ tags: [journal]
100
+ timestamp: <ISO-8601>
101
+ status: active
102
+ ---
103
+
104
+ # <YYYY-MM-DD>
105
+
106
+ ## HH:MM — <outcome>
107
+ <what changed, evidence of completion, consequential decisions, and only context
108
+ git cannot explain>
109
+
110
+ Against: <optional repo-relative plan path, e.g. PLAN.md>
111
+
112
+ Resume: <one exact next action> — open loops: <none or concise list>
113
+ ```
114
+
115
+ Append one section per coherent substantive task. The last line of every section
116
+ must be its `Resume:` line.
117
+
118
+ ## `decisions/<YYYY-MM-DD>-<slug>.md`
119
+
120
+ ```markdown
121
+ ---
122
+ type: Decision
123
+ title: <Decision title>
124
+ description: <one-line summary>
125
+ tags: [<topic>]
126
+ timestamp: <ISO-8601>
127
+ status: open # open → deferred → decided → superseded
128
+ resource: <optional link to PR/code/discussion>
129
+ ---
130
+
131
+ # <Decision title>
132
+
133
+ ## Context
134
+ <why this choice matters and what constraint forced it>
135
+
136
+ ## Options
137
+ - <option A> — <tradeoff>
138
+ - <option B> — <tradeoff>
139
+
140
+ ## Outcome
141
+ <For open: what input is needed. For deferred: what it awaits. For decided:
142
+ what was chosen, why, and when. For superseded: link the replacement.>
143
+ ```
144
+
145
+ ## `attention/<YYYY-MM-DD>-<slug>.md`
146
+
147
+ Residue still occupying working memory after a hop. Not a decision (no options).
148
+ Not a note (not a durable fact). Not a todo. Body is 2–8 lines of why forgetting
149
+ it would cost a reload. No checklist.
150
+
151
+ ```markdown
152
+ ---
153
+ type: Attention
154
+ title: <short residue>
155
+ description: <one-line summary>
156
+ tags: []
157
+ timestamp: <ISO-8601>
158
+ status: open # open | later | resolved
159
+ kind: direction # direction | concern | thread
160
+ from: <optional person>
161
+ against: <optional repo-relative path, e.g. PLAN.md>
162
+ ---
163
+
164
+ # <short residue>
165
+
166
+ <Why this would cost a reload if forgotten. No checklist.>
167
+ ```
168
+
169
+ ## `notes/<slug>.md`
170
+
171
+ ```markdown
172
+ ---
173
+ type: Note
174
+ title: <Fact title>
175
+ description: <one-line summary>
176
+ tags: [<topic>]
177
+ timestamp: <ISO-8601>
178
+ status: active
179
+ resource: <optional link to the code this describes>
180
+ ---
181
+
182
+ # <Fact title>
183
+
184
+ <The durable, non-obvious, repository-specific fact and the evidence supporting
185
+ it. Link related concepts with paths relative to this file.>
186
+ ```