@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,17 @@
1
+ {
2
+ "name": "mental",
3
+ "owner": {
4
+ "name": "Ali Farahat",
5
+ "url": "https://github.com/afaraha8403"
6
+ },
7
+ "metadata": {
8
+ "description": "Never reconstruct where you left off."
9
+ },
10
+ "plugins": [
11
+ {
12
+ "name": "mental",
13
+ "source": "./",
14
+ "description": "Never reconstruct where you left off. Mental keeps the resume, the decisions, and what's still in the air — so you and your agents continue as if the last session never ended."
15
+ }
16
+ ]
17
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "mental",
3
+ "displayName": "Mental",
4
+ "version": "0.2.0",
5
+ "description": "Never reconstruct where you left off. Mental keeps the resume, the decisions, and what's still in the air — so you and your agents continue as if the last session never ended.",
6
+ "author": {
7
+ "name": "Ali Farahat",
8
+ "url": "https://github.com/afaraha8403"
9
+ },
10
+ "homepage": "https://github.com/afaraha8403/mental#readme",
11
+ "repository": "https://github.com/afaraha8403/mental",
12
+ "license": "MIT",
13
+ "keywords": [
14
+ "continuity",
15
+ "journal",
16
+ "decisions",
17
+ "okf",
18
+ "skills",
19
+ "mcp"
20
+ ],
21
+ "mcpServers": "./.mcp.json"
22
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "mental",
3
+ "version": "0.2.0",
4
+ "description": "Never reconstruct where you left off. Mental keeps the resume, the decisions, and what's still in the air — so you and your agents continue as if the last session never ended.",
5
+ "author": {
6
+ "name": "Ali Farahat",
7
+ "url": "https://github.com/afaraha8403"
8
+ },
9
+ "homepage": "https://github.com/afaraha8403/mental#readme",
10
+ "repository": "https://github.com/afaraha8403/mental",
11
+ "license": "MIT",
12
+ "keywords": [
13
+ "continuity",
14
+ "journal",
15
+ "decisions",
16
+ "okf",
17
+ "skills",
18
+ "mcp"
19
+ ],
20
+ "logo": "assets/logo.svg"
21
+ }
package/.mcp.json ADDED
@@ -0,0 +1,8 @@
1
+ {
2
+ "mcpServers": {
3
+ "mental": {
4
+ "command": "node",
5
+ "args": ["${CLAUDE_PLUGIN_ROOT}/bin/cli.mjs", "serve"]
6
+ }
7
+ }
8
+ }
package/CHANGELOG.md ADDED
@@ -0,0 +1,42 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.2.0] - 2026-08-26
11
+
12
+ ### Added
13
+
14
+ - Ranked FTS search (`bm25`) with snippets, and SQL-side `--type` / `--status` / `--tag` / `--kind` filters so a typed query cannot be crowded out by untyped matches.
15
+ - `mental list` includes each concept's `description`; `--kind` filters attention on list and search.
16
+ - `mental show` returns `backlinks` from the derived link index (file-scan fallback).
17
+ - MCP `list` tool; search accepts the same typed filters as the CLI; tool results are compact JSON.
18
+ - Agent **Mental receipt** at the end of a turn that used the CLI: `<br>`, title `🧠 Mental`, then type lines (📓 journal, 🚦 attention, 🎯 decision, 📝 note, 🔍 read). Example in the skill; the always-on rule points at it. TTY writes use the same type emojis. `--json` stays ASCII (`MENTAL_ASCII=1` strips emoji).
19
+ - `mental install` copies the skill to `~/.config/opencode/skills/mental` (OpenCode).
20
+
21
+ ### Changed
22
+
23
+ - README now shows the logo, explains the [Agent Plugins 1.0.0](https://agent-plugins.org/specification) packaging, and includes copy-paste install prompts for Cursor, Claude Code, VS Code, and GitHub Copilot.
24
+ - npm package is `@balacode/mental` (unscoped `mental` is taken). The CLI bin stays `mental`.
25
+
26
+ ## [0.1.0] - 2026-08-26
27
+
28
+ First public release of the Mental CLI.
29
+
30
+ ### Added
31
+
32
+ - Standalone Mental CLI: on a TTY, no args prints a one-shot heartbeat and exits; named commands are one-shot; agents use `--json`.
33
+ - UUID identity in `~/.mental/bindings.json`, with `remap` / `split` / `link` and `local --import` / `--move`.
34
+ - Attention residue (`mental attention`) and `journal --against` so heartbeat carries what is still in the air.
35
+ - Agent Plugins 1.0.0 package: root `plugin.json`, skill at `skills/mental/`, MCP at `mcp.json` (stdio `./bin/cli.mjs serve`).
36
+ - Cursor / Claude Code shims: `.cursor-plugin/plugin.json` (SVG logo) and `.claude-plugin/plugin.json` (`displayName: Mental`).
37
+ - `install --mcp` registers `serve`; `decide` updates by title so an open decision can close.
38
+ - Install, doctor, uninstall; hooks stay off by default.
39
+
40
+ [Unreleased]: https://github.com/afaraha8403/mental/compare/v0.2.0...HEAD
41
+ [0.2.0]: https://github.com/afaraha8403/mental/releases/tag/v0.2.0
42
+ [0.1.0]: https://github.com/afaraha8403/mental/releases/tag/v0.1.0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ali Farahat
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,277 @@
1
+ <p align="center">
2
+ <img src="assets/logo.svg" alt="Mental" width="128" height="128">
3
+ </p>
4
+
5
+ # Mental
6
+
7
+ Local-first continuity layer for you and your coding agents.
8
+
9
+ Git records **what** changed. Mental records the small amount git cannot explain: where you left off, why a decision was made, what is still in the air after a hop, and the next exact action. **OKF markdown is the source of truth.** SQLite is a derived cache. Agents call `mental … --json` — they do not grep YAML.
10
+
11
+ - **Repo:** https://github.com/afaraha8403/mental
12
+ - **Spec:** [PLAN.md](./PLAN.md)
13
+ - **Plugin standard:** [Agent Plugins 1.0.0](https://agent-plugins.org/specification)
14
+
15
+ Mental is **not** a Balakit plugin. Default data lives in `~/.mental` (UUID bindings). Project `./.mental` only after `mental local`.
16
+
17
+ ## Install
18
+
19
+ ### Paste this into your agent
20
+
21
+ Copy the block into Cursor, Claude Code, Copilot, Codex, or any other coding agent:
22
+
23
+ ```text
24
+ Install Mental from https://github.com/afaraha8403/mental.
25
+
26
+ Mental is a local-first continuity layer. Git records what changed; Mental records where we left off, why a decision was made, and what is still in the air.
27
+
28
+ The repo is an Agent Plugins 1.0.0 package (https://agent-plugins.org/specification): plugin.json at the repo root, skill at skills/mental/, MCP at mcp.json.
29
+
30
+ Use this client's native plugin install if you have one, then put the CLI on PATH and finish setup:
31
+
32
+ npm i -g @balacode/mental
33
+ mental install
34
+ mental doctor
35
+
36
+ Do not enable hooks unless I ask. Optional MCP is `mental install --mcp`. After doctor, tell me what it reports.
37
+ ```
38
+
39
+ ### Client one-liners
40
+
41
+ **Cursor** — paste in Agent chat:
42
+
43
+ ```text
44
+ /add-plugin https://github.com/afaraha8403/mental
45
+ ```
46
+
47
+ **Claude Code:**
48
+
49
+ ```text
50
+ /plugin marketplace add afaraha8403/mental
51
+ /plugin install mental@mental
52
+ ```
53
+
54
+ **VS Code** — Command Palette → **Chat: Install Plugin From Source**, then:
55
+
56
+ ```text
57
+ https://github.com/afaraha8403/mental
58
+ ```
59
+
60
+ **GitHub Copilot CLI:**
61
+
62
+ ```bash
63
+ copilot plugin marketplace add afaraha8403/mental
64
+ copilot plugin install mental@mental
65
+ ```
66
+
67
+ Plugin install loads the skill and MCP. Still run `mental install` so the CLI, skill, and tiny always-on rule land on this machine.
68
+
69
+ ### CLI
70
+
71
+ ```bash
72
+ npm i -g @balacode/mental
73
+ mental install
74
+ ```
75
+
76
+ Last install wins. That puts `mental` on PATH (typically `~/.local/bin/mental`), copies the skill + tiny always-on rule into `~/.claude`, `~/.cursor`, `~/.agents`, and `~/.config/opencode`, and creates a `~/.mental` skeleton. It does **not** turn on hooks or MCP.
77
+
78
+ From a clone, without npm:
79
+
80
+ ```bash
81
+ cd /path/to/mental
82
+ node bin/cli.mjs install --json
83
+ ```
84
+
85
+ ```bash
86
+ mental doctor # PATH, bindings, ignore, skills
87
+ mental doctor --fix-ignore # add .mental/ and .mental-id to your global git excludes
88
+ ```
89
+
90
+ ## Agent Plugins 1.0.0
91
+
92
+ Mental is packaged as a portable [Agent Plugins](https://agent-plugins.org/) 1.0.0 plugin — the vendor-neutral format maintained by Amazon, Cursor, Microsoft, OpenAI, and Vercel. Compatible clients (Cursor, VS Code, GitHub Copilot, ChatGPT/Codex, Kiro) load the same directory: no per-client rewrite of the skill or MCP server.
93
+
94
+ The spec's interoperability floor is small and closed:
95
+
96
+ | Piece | Where | Role |
97
+ | --- | --- | --- |
98
+ | `plugin.json` | repo root | Manifest (`$schema` + `name`). The portable schema has no icon field. |
99
+ | `skills/mental/` | Agent Skills | Procedure: when to journal, CLI contract, privacy. |
100
+ | `mcp.json` | repo root | stdio MCP → `./bin/cli.mjs serve` (`cwd` `${PLUGIN_ROOT}`) |
101
+
102
+ Cursor extras live in `.cursor-plugin/plugin.json` (logo). Claude Code extras live in `.claude-plugin/plugin.json` (`displayName: Mental`) and `.claude-plugin/marketplace.json`. Rules and hooks are **not** portable v1 components — they still come from `mental install` / `mental hooks on`.
103
+
104
+ Plugin install loads the skill and MCP. The CLI remains the contract: humans type `mental`; agents call `mental … --json`.
105
+
106
+ ## How you use it (human)
107
+
108
+ On a TTY, in any git repo:
109
+
110
+ ```bash
111
+ mental
112
+ ```
113
+
114
+ Prints a one-shot **heartbeat** and exits — resume, last outcome, git, residue in the air, unsettled decisions. Not a menu. UUID / root / index live on `where` and `doctor`.
115
+
116
+ Daily loop:
117
+
118
+ 1. `mental` — where did I leave off?
119
+ 2. Do the work.
120
+ 3. At a real task boundary (not every chat turn):
121
+
122
+ ```bash
123
+ mental journal --title "What landed" --body "Evidence git cannot see." --resume "Exact next action — open loops: none" --against PLAN.md
124
+ ```
125
+
126
+ Lookup:
127
+
128
+ ```bash
129
+ mental status # git + resume + residue + open decisions + notes (writes status/current.md cache)
130
+ mental heartbeat --json # same pulse as `mental` on a TTY; agents use this
131
+ mental where # root, uuid, mode — read-only, does not create identity
132
+ mental search overlay
133
+ mental list --type Decision --kind direction
134
+ mental show notes/some-fact.md
135
+ ```
136
+
137
+ Write a decision only when it constrains the future. Write attention for residue that is not a choice (Tom said X, a concern, later):
138
+
139
+ ```bash
140
+ mental decide --title "Heartbeat only, no standing TUI" --status decided
141
+ mental attention --title "Tom said ship the pointer not the dump" --kind direction --from Tom
142
+ mental attention --title "Tom said ship the pointer not the dump" --status resolved
143
+ mental note --title "Identity is a UUID in bindings.json"
144
+ ```
145
+
146
+ Same `--title` updates the existing decision (paths are identities). `--path` targets a specific file.
147
+
148
+ Mental is **not** a todo app. Do not store transcripts. Do not duplicate PLAN.md.
149
+
150
+ Non-TTY (pipes, agents) always pass `--json`. No args + not a TTY prints help and exits 2.
151
+
152
+ ## How agents use it
153
+
154
+ Always:
155
+
156
+ ```bash
157
+ mental where --json
158
+ mental heartbeat --json
159
+ ```
160
+
161
+ ```bash
162
+ mental journal --title "…" --body "…" --resume "…" --against PLAN.md --json
163
+ mental attention --title "…" --kind concern --status open --json
164
+ mental decide --title "…" --status open --json
165
+ mental decide --title "…" --status decided --json
166
+ mental search "…" --json
167
+ mental list --type Decision --json
168
+ mental show notes/some-fact.md --json
169
+ mental status --json
170
+ ```
171
+
172
+ Mid-chat, not just start/finish: search decisions before changing an approach, record attention the moment residue surfaces, and re-pulse `mental heartbeat --json` whenever other agents may have written — it is cheap and derives git live.
173
+
174
+ Do not grep `.mental` or parse YAML. If `mental` is missing, continue the coding task (fail open) and mention install.
175
+
176
+ Turns that invoked `mental` end with `<br>`, then the title `🧠 Mental`, then one type line per write/read (see the skill).
177
+
178
+ ## Identity (UUID, not the folder)
179
+
180
+ Identity lives in `~/.mental/bindings.json`. Origin is a hint (SSH ≡ HTTPS). Two clones of the same origin share one brain until you split.
181
+
182
+ | Situation | Command |
183
+ | --- | --- |
184
+ | This clone should use an existing UUID | `mental remap --to <uuid>` (or `mental link --to <uuid>`) |
185
+ | This clone should diverge | `mental split` (`--copy` keeps OKF files) |
186
+ | List bindings | `mental remap` |
187
+ | Opt in to `./.mental` in this repo | `mental doctor --fix-ignore` then `mental local` |
188
+ | Copy home slice into `./.mental` | `mental local --import` |
189
+ | Same, and mark store=local | `mental local --move` |
190
+
191
+ `where` does **not** create a UUID. First write (`status`, `journal`, `install`, …) does. Leftover Balakit `./.mental` (no `.mental-local` marker) is ingested into `~/.mental/projects/<uuid>/` on that write; the leftover folder is not deleted.
192
+
193
+ ## Optional: hooks and MCP
194
+
195
+ Default **off**. Skill + rule are the contract.
196
+
197
+ ```bash
198
+ mental hooks on # Cursor sessionStart + Claude SessionStart/PreCompact → mental status --json
199
+ mental hooks off
200
+ mental serve # MCP stdio: heartbeat, where, status, search, list, show, journal, attention, decide, note
201
+ mental install --mcp # register `mental serve` in ~/.cursor/mcp.json + ~/.claude.json; does not enable hooks
202
+ ```
203
+
204
+ MCP is how tool-only agents (parallel sessions, orchestrators) re-pulse and record mid-chat. `mental uninstall` removes the MCP entries too.
205
+
206
+ ```bash
207
+ mental uninstall # remove skill/rule/hooks copies; ~/.mental stays
208
+ mental uninstall --delete-data --confirm DELETE # wipe ~/.mental too
209
+ ```
210
+
211
+ ## Commands
212
+
213
+ | Command | What it does |
214
+ | --- | --- |
215
+ | `mental` | Heartbeat (TTY): resume, last outcome, git, residue, unsettled decisions; then exit. Non-TTY → help, exit 2 |
216
+ | `mental heartbeat` | Same pulse; agents pass `--json` |
217
+ | `mental where` | Active bundle: `root`, `id`, `mode`, `reason`, `gitRoot` (read-only) |
218
+ | `mental status` | Git + Resume + residue + open/deferred decisions + notes; writes `status/current.md`; first write creates identity |
219
+ | `mental search <q>` | Query the derived index (`--type`, `--status`, `--tag`, `--kind`); hits include `description` + `snippet` |
220
+ | `mental list` | List concepts (`--type`, `--status`, `--tag`, `--kind`) |
221
+ | `mental show <path>` | One OKF file relative to the bundle root (includes `backlinks`) |
222
+ | `mental reindex` | Rebuild `${XDG_CACHE_HOME:-~/.cache}/mental/<uuid>.sqlite` |
223
+ | `mental journal --title --body --resume [--against]` | Append today’s journal section |
224
+ | `mental attention --title --kind` | Create or update residue (`--status resolved` closes it) |
225
+ | `mental decide --title` | Create or update a decision (`--status decided` closes by title; `--path` targets a file) |
226
+ | `mental note --title` | Scaffold a note |
227
+ | `mental local [--import \| --move]` | Project `./.mental` after ignore check |
228
+ | `mental remap [--to id]` | List or retarget this clone’s UUID |
229
+ | `mental split [--copy]` | New UUID for this clone |
230
+ | `mental link --to <id>` | Point this clone at an existing UUID |
231
+ | `mental install` | User skill + rule; `~/.mental` skeleton; CLI on PATH; `--mcp` registers MCP config |
232
+ | `mental uninstall` | Remove installed skill/rule/hooks/MCP entries |
233
+ | `mental hooks on\|off` | Optional session hooks |
234
+ | `mental serve` | Optional MCP stdio (full command surface) |
235
+ | `mental doctor` | PATH, bindings, ignore, skills. `--fix-ignore` adds `.mental/` to global excludes |
236
+
237
+ Global flags: `--json`, `--dir <path>` (same as `MENTAL_DIR`).
238
+
239
+ ## Privacy
240
+
241
+ - Default store: `~/.mental/` (never commit).
242
+ - Project `.mental/` is opt-in and must be gitignored (`mental doctor --fix-ignore`). Agents must not edit `.gitignore`.
243
+ - Never store secrets, tokens, or private keys in Mental files.
244
+ - Uninstall does not delete OKF unless you type `DELETE`.
245
+
246
+ ## Tests
247
+
248
+ ```bash
249
+ npm test
250
+ ```
251
+
252
+ ## Layout
253
+
254
+ OKF files under `~/.mental/projects/<uuid>/` (or `./.mental` after `mental local`):
255
+
256
+ ```text
257
+ journal/YYYY-MM-DD.md
258
+ decisions/YYYY-MM-DD-slug.md
259
+ attention/YYYY-MM-DD-slug.md
260
+ notes/slug.md
261
+ status/current.md # disposable cache, not SoT
262
+ ```
263
+
264
+ Index: `${XDG_CACHE_HOME:-~/.cache}/mental/<uuid>.sqlite` (rebuildable).
265
+
266
+ Agent Plugin (this repo):
267
+
268
+ ```text
269
+ plugin.json # Agent Plugins 1.0.0 manifest
270
+ mcp.json # stdio MCP → ./bin/cli.mjs serve
271
+ assets/logo.svg # Cursor logo (portable spec has no icon field)
272
+ .cursor-plugin/plugin.json
273
+ .claude-plugin/plugin.json # displayName: Mental
274
+ skills/mental/SKILL.md
275
+ rules/mental.mdc # Cursor always-on pointer (install copies it)
276
+ hooks/session-start.sh # optional; mental hooks on
277
+ ```