projectstore-claude 0.29.3 → 0.30.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 (57) hide show
  1. package/README.md +13 -12
  2. package/bin/projectstore-claude.mjs +2 -2
  3. package/node_modules/projectstore/.claude-plugin/marketplace.json +1 -1
  4. package/node_modules/projectstore/.claude-plugin/plugin.json +1 -1
  5. package/node_modules/projectstore/README.md +153 -77
  6. package/node_modules/projectstore/commands/bind.md +6 -17
  7. package/node_modules/projectstore/commands/doctor.md +12 -7
  8. package/node_modules/projectstore/commands/statusline.md +1 -1
  9. package/node_modules/projectstore/commands/story.md +15 -2
  10. package/node_modules/projectstore/docs/extending.md +11 -6
  11. package/node_modules/projectstore/docs/getting-started.md +21 -1
  12. package/node_modules/projectstore/docs/harnesses.md +13 -10
  13. package/node_modules/projectstore/docs/how-it-works.md +6 -4
  14. package/node_modules/projectstore/harnesses/claude-code.json +16 -15
  15. package/node_modules/projectstore/harnesses/codex.json +12 -13
  16. package/node_modules/projectstore/hooks/band.tsx +48 -20
  17. package/node_modules/projectstore/hooks/pre-compact.mjs +7 -10
  18. package/node_modules/projectstore/hooks/session-rules.mjs +14 -8
  19. package/node_modules/projectstore/hooks/session-start.mjs +50 -18
  20. package/node_modules/projectstore/hooks/session-stop.mjs +8 -6
  21. package/node_modules/projectstore/package.json +11 -2
  22. package/node_modules/projectstore/scripts/band-shared.mjs +141 -24
  23. package/node_modules/projectstore/scripts/band.mjs +72 -21
  24. package/node_modules/projectstore/scripts/binding.mjs +616 -85
  25. package/node_modules/projectstore/scripts/build-adapters.mjs +73 -29
  26. package/node_modules/projectstore/scripts/cli.mjs +1015 -185
  27. package/node_modules/projectstore/scripts/codemap.mjs +22 -7
  28. package/node_modules/projectstore/scripts/convergence.mjs +253 -83
  29. package/node_modules/projectstore/scripts/diff-refs.mjs +14 -8
  30. package/node_modules/projectstore/scripts/doctor-report.mjs +91 -23
  31. package/node_modules/projectstore/scripts/doctor.mjs +1317 -371
  32. package/node_modules/projectstore/scripts/draft.mjs +5 -2
  33. package/node_modules/projectstore/scripts/fetch-shell.mjs +188 -39
  34. package/node_modules/projectstore/scripts/graph.mjs +19 -13
  35. package/node_modules/projectstore/scripts/harness.mjs +123 -48
  36. package/node_modules/projectstore/scripts/install-harness.mjs +3532 -618
  37. package/node_modules/projectstore/scripts/kanban.mjs +2 -1
  38. package/node_modules/projectstore/scripts/lib.mjs +694 -159
  39. package/node_modules/projectstore/scripts/mcp.mjs +386 -105
  40. package/node_modules/projectstore/scripts/portable-registration.mjs +224 -51
  41. package/node_modules/projectstore/scripts/provenance.mjs +26 -10
  42. package/node_modules/projectstore/scripts/query.mjs +378 -80
  43. package/node_modules/projectstore/scripts/reconcile.mjs +55 -18
  44. package/node_modules/projectstore/scripts/run-host.mjs +62 -17
  45. package/node_modules/projectstore/scripts/scaffold.mjs +89 -28
  46. package/node_modules/projectstore/scripts/setup.mjs +987 -0
  47. package/node_modules/projectstore/scripts/stages.mjs +5 -1
  48. package/node_modules/projectstore/scripts/statusline-launcher.mjs +36 -11
  49. package/node_modules/projectstore/scripts/statusline.mjs +32 -14
  50. package/node_modules/projectstore/scripts/story-section.mjs +39 -17
  51. package/node_modules/projectstore/scripts/surfaces.mjs +416 -95
  52. package/node_modules/projectstore/scripts/term.mjs +382 -97
  53. package/node_modules/projectstore/scripts/tokens.mjs +106 -28
  54. package/node_modules/projectstore/scripts/touch-session.mjs +109 -70
  55. package/node_modules/projectstore/scripts/version-guard.mjs +74 -27
  56. package/node_modules/projectstore/scripts/worktree.mjs +16 -5
  57. package/package.json +3 -3
package/README.md CHANGED
@@ -1,25 +1,26 @@
1
1
  # projectstore-claude
2
2
 
3
- The Claude Code installer for [projectstore](https://www.npmjs.com/package/projectstore): the core, pinned at exactly this version and bundled inside this tarball, with the harness fixed. One command, from a terminal **outside** a Claude Code session:
3
+ > **To install ProjectStore, run `npx projectstore setup` from a terminal in your project.** This package is a release artifact; you do not need it.
4
+
5
+ The Claude Code distribution shell of [projectstore](https://www.npmjs.com/package/projectstore): the core, pinned at exactly this version and bundled inside this tarball, with the harness fixed to Claude Code.
6
+
7
+ From a terminal in your project:
4
8
 
5
9
  ```sh
6
- npx projectstore-claude install --project "$PWD"
10
+ npx projectstore setup
7
11
  ```
8
12
 
9
- It registers the plugin for that checkout at the host's local scope. It prints its plan first — every write and every host command, verbatim — and at a terminal asks `◆ Apply N changes? [Y/n]` before anything runs; then each step as it runs, and what to do next. Without a terminal (a script, CI, an agent's tool) naming the shell is the confirmation; `--json` never asks. Restart Claude Code afterwards.
10
-
11
- - See before you write: `npx projectstore-claude plan --project "$PWD"` prints the same plan and writes nothing; `--verbose` adds every row's reasoning; `npx projectstore-claude <verb> --help` lists a verb's options with examples.
13
+ Setup finds the coding agents the project uses, Claude Code among them, and installs ProjectStore for each, with a vault for the project's notes. It asks a few questions, prints one plan — every write and every host command, verbatim — and asks once before anything runs. For Claude Code it registers the plugin for that checkout at the host's local scope, through a small local marketplace under your Claude home. Restart Claude Code afterwards.
12
14
 
13
- - Upgrade, or pin: `npx projectstore-claude@<version> upgrade --project "$PWD"` — the version you name is the version you run.
14
- - Behind a registry mirror: if `npx` answers `could not determine executable to run`, the mirror's index knows only the reserved `0.0.1` placeholder — name the version, and if needed the public registry: `npx --registry https://registry.npmjs.org projectstore-claude@<version> install --project "$PWD"`.
15
- - Uninstall: `npx projectstore-claude uninstall --project "$PWD"` — forgets the registration for that checkout and nothing else; your vault is plain markdown and stays yours.
16
- - `doctor`, `status`, `search` and the other read verbs pass through unchanged: `npx projectstore-claude doctor --json`.
15
+ Upgrade, or pin, from the same place; the version you name is the version you run:
17
16
 
18
- This shell is `projectstore <verb> --harness claude-code` and nothing more. `bin/projectstore-claude.mjs` locates the bundled core under `node_modules/projectstore/` and execs it; the core's low-level form — `npx projectstore install --harness claude-code --project "$PWD"` — is exactly what runs. A different `--harness` is refused (exit 2). The shell carries no plugin of its own: the plugin Claude Code loads is the bundled core, registered through a small local marketplace under your Claude home.
17
+ ```sh
18
+ npx projectstore@<version> upgrade
19
+ ```
19
20
 
20
- Why from a terminal: the host CLI and a live session both rewrite the same settings files, so the core defers the registration inside a session and says so.
21
+ This shell's bin is `projectstore <verb> --harness claude-code` and nothing more. `bin/projectstore-claude.mjs` locates the bundled core under `node_modules/projectstore/` and execs it; a different `--harness` is refused (exit 2). The shell carries no plugin of its own: the plugin Claude Code loads is the bundled core.
21
22
 
22
- - Docs: https://github.com/SmartAndPoint/ProjectStore#install--one-message
23
+ - Docs: https://github.com/SmartAndPoint/ProjectStore#install
23
24
  - Source: https://github.com/SmartAndPoint/ProjectStore
24
25
  - Issues: https://github.com/SmartAndPoint/ProjectStore/issues
25
26
 
@@ -24,7 +24,7 @@ const HARNESS = "claude-code";
24
24
  // scripts/cli.mjs; the packaging test pins it). Any other verb — doctor,
25
25
  // status, search, --version — passes through untouched: the core refuses an
26
26
  // option a verb does not declare, so a blanket insert would break `doctor`.
27
- const HARNESS_VERBS = new Set(["plan","install","uninstall","upgrade","agents"]);
27
+ const HARNESS_VERBS = new Set(["setup","plan","install","uninstall","upgrade","agents"]);
28
28
 
29
29
  // The bundled core, by path — never by package resolution: a hoisted or global
30
30
  // copy at another version is exactly the pairing the pin exists to prevent,
@@ -57,7 +57,7 @@ function fixHarness(argv) {
57
57
  }
58
58
  }
59
59
  const other = given.find((g) => g !== HARNESS);
60
- if (other !== undefined) return { error: `installs for ${HARNESS} only — \`--harness ${other}\` names another harness. Run that harness's shell, or the core: npx projectstore <verb> --harness ${other} …` };
60
+ if (other !== undefined) return { error: `installs for ${HARNESS} only — \`--harness ${other}\` names another harness. Run the core: npx projectstore <verb> --harness ${other} …` };
61
61
  if (given.length) return { argv }; // named already: pass through, never twice (the core's option repeats)
62
62
  const at = scan.findIndex((a) => !a.startsWith("-"));
63
63
  if (at === -1 || !HARNESS_VERBS.has(scan[at])) return { argv };
@@ -12,7 +12,7 @@
12
12
  "name": "projectstore",
13
13
  "displayName": "projectstore",
14
14
  "description": "📚 Your agent runs the project through a verified loop: task → artifact (ADR · spec · epic · story) → adversarial critic → backlog → planner → reviewer → done. Plain markdown in an Obsidian-friendly vault, every write approved by you — and any model can pick the project up tomorrow.",
15
- "version": "0.29.3",
15
+ "version": "0.30.0",
16
16
  "author": {
17
17
  "name": "Evgenii Konev",
18
18
  "email": "ekonev@smartandpoint.com",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "projectstore",
3
3
  "displayName": "projectstore",
4
- "version": "0.29.3",
4
+ "version": "0.30.0",
5
5
  "description": "Your agent runs the project through a verified loop: task → artifact (ADR / spec / epic / story) → adversarial critic → backlog → planner → reviewer → done. Plain markdown in git — any model can pick the project up tomorrow.",
6
6
  "author": {
7
7
  "name": "Evgenii Konev @ SmartAndPoint",
@@ -4,7 +4,7 @@
4
4
 
5
5
  [![release](https://img.shields.io/github/v/release/SmartAndPoint/ProjectStore?label=release)](https://github.com/SmartAndPoint/ProjectStore/releases) [![license](https://img.shields.io/github/license/SmartAndPoint/ProjectStore?label=license)](./LICENSE) [![Star on GitHub](https://img.shields.io/badge/%E2%AD%90-star_us-yellow?logo=github)](https://github.com/SmartAndPoint/ProjectStore/stargazers)
6
6
 
7
- A project workflow plugin for [Claude Code](https://claude.com/claude-code) and [OpenAI Codex](https://developers.openai.com/codex/) (experimental). Both are released together at one version, and each installs with one command.
7
+ A project workflow plugin for [Claude Code](https://claude.com/claude-code) and [OpenAI Codex](https://developers.openai.com/codex/) (experimental). Both are released together at one version, and one command sets a project up for either or both: see [Install](#install).
8
8
 
9
9
  ---
10
10
 
@@ -75,24 +75,40 @@ In Claude Code a band above the prompt goes further (experimental): the session'
75
75
 
76
76
  Open the vault in [Obsidian](https://obsidian.md) and you get the graph view and the board for free. Don't use Obsidian? Everything renders on GitHub and in any editor.
77
77
 
78
- ## Install — one message
78
+ ## Install
79
79
 
80
- Open Claude Code in your project and say:
80
+ From a terminal in your project:
81
81
 
82
- > Install the projectstore plugin from https://github.com/SmartAndPoint/ProjectStore and set it up for this project.
82
+ ```
83
+ npx projectstore setup
84
+ ```
83
85
 
84
- That's the whole setup. Claude adds the marketplace, installs the plugin, and walks you through binding a vault, scaffolding it and wiring the status line — every step previewed, nothing written without your Yes.
86
+ Setup finds the coding agents the project uses — Claude Code, Codex or both — and installs ProjectStore for each, with a vault for the project's notes. At a terminal it asks a few questions: which folder is the project, which agents to install for, where the vault lives (an existing folder is bound; a missing or empty one becomes a new vault, with its own git repository and the layout's folders) and whether to show ProjectStore in the status line. Then it prints one plan — every file it writes and every host command, verbatim — and asks once before it writes anything. Restart the agent afterwards; Codex asks you to approve the ProjectStore hooks once.
85
87
 
86
- **On Codex**, run one command from a terminal in your project:
88
+ `npx projectstore setup --dry-run` shows the questions and the plan and writes nothing. Without a terminal (a script, CI, an agent's tool) nothing is asked: `--harness <id>` names an agent and is the confirmation, and `--vault <path>` names the vault. `npx projectstore setup --help` lists the rest.
89
+
90
+ If you prefer a global command:
87
91
 
88
92
  ```
89
- npx projectstore-codex install --project "$PWD"
93
+ npm install -g projectstore
94
+ projectstore setup
90
95
  ```
91
96
 
92
- Then restart Codex, approve the ProjectStore hooks when it asks, and run `$projectstore-bind ~/Documents/my-project-vault`. Codex support is newer and still labelled experimental: [`docs/harnesses.md`](./docs/harnesses.md#codex) says what has been verified and what has not. A project can be worked from both agents: they share the binding in `.projectstore/`, and each keeps its own overlay and session state beside it ([running both over one project](./docs/harnesses.md#running-both-over-one-project)).
97
+ Behind a registry mirror (often a company's), `npx` runs the newest `projectstore` the mirror knows. That can be a release older than setup, which answers that `setup` is an unknown verb, or no release at all. Name the version, and if that is not enough, the public registry:
93
98
 
94
- <details>
95
- <summary>Prefer to type it yourself?</summary>
99
+ ```
100
+ npm_config_registry=https://registry.npmjs.org npx projectstore@<version> setup
101
+ ```
102
+
103
+ npm reads that variable wherever it runs, so the Codex plugin setup fetches comes from the same registry.
104
+
105
+ ### In a Claude Code session
106
+
107
+ Open Claude Code in your project and say:
108
+
109
+ > Install the projectstore plugin from https://github.com/SmartAndPoint/ProjectStore and set it up for this project.
110
+
111
+ Claude adds the git marketplace, installs the plugin, and walks you through binding a vault, scaffolding it and wiring the status line — every step previewed, nothing written without your Yes. Or type it yourself:
96
112
 
97
113
  ```
98
114
  /plugin marketplace add SmartAndPoint/ProjectStore
@@ -103,49 +119,31 @@ Then restart Codex, approve the ProjectStore hooks when it asks, and run `$proje
103
119
 
104
120
  One switch worth flipping: Claude Code does **not** auto-update third-party plugins by default — `/plugin` → **Marketplaces** → **SmartAndPoint** → toggle **auto-update** on. If you skip it, `/projectstore:doctor` will remind you later with the exact setting.
105
121
 
106
- Contributors: `git clone` this repo, then `claude --plugin-dir ./ProjectStore`.
107
-
108
- **Or from npm, in one command** — from a terminal, not inside a Claude Code session:
122
+ Contributors: `git clone` this repo, then run Claude Code from the clone's parent folder:
109
123
 
110
124
  ```
111
- npx projectstore-claude install --project "$PWD"
125
+ claude --plugin-dir ./ProjectStore
112
126
  ```
113
127
 
114
- The same tree is published to npm as [`projectstore`](https://www.npmjs.com/package/projectstore) — one source package carrying every harness's manifest — and `projectstore-claude` is its Claude Code shell: the core pinned at the same version and bundled inside, the harness fixed, so the one command has the same shape on every harness. It registers the plugin with Claude Code: it writes a small local marketplace of its own under your Claude home, then drives `claude plugin marketplace add` / `plugin install` **at local scope**, so the registration lands in this checkout's `.claude/settings.local.json` and nowhere else. It prints its plan first — every file it writes and every host command, verbatim — and at a terminal asks `◆ Apply N changes? [Y/n]`; then it shows each step as it runs and what to do next. Without a terminal (a script, CI, an agent's tool) naming the harness is the confirmation. `plan` prints the same plan and writes nothing; `--verbose` adds every row's reasoning; `npx projectstore-claude <verb> --help` lists a verb's options with examples. Restart Claude Code afterwards. A git-marketplace copy already enabled for the checkout is silenced there (not globally) so the plugin does not load twice; `uninstall` turns it back on. Pin or upgrade with `npx projectstore-claude@<version> upgrade --project "$PWD"` — the version you name is the version you run. The core's low-level form, `npx projectstore <verb> --harness claude-code …`, is exactly what the shell runs. bun works the same on the packed bin.
128
+ <details>
129
+ <summary>What setup does for each agent, the low-level verbs, the CLI and MCP</summary>
115
130
 
116
- **Codex has its own shell with the same one-command shape:**
117
- `npx projectstore-codex install --project "$PWD"`. It carries a Codex
118
- plugin manifest, namespaced workflow and role skills, lifecycle hooks, and
119
- the exact bundled core. It stages a stable marketplace under `CODEX_HOME`,
120
- drives `codex plugin marketplace add` and `codex plugin add`, then reads the
121
- installation back and verifies its version and payload digest. Before it
122
- changes anything it asks Codex for that read-back (`codex plugin list --json`),
123
- so a Codex too old to answer stops the registration before it changes anything
124
- and tells you to upgrade Codex. Restart Codex,
125
- approve the hooks, and run `$projectstore-bind <vault-path>`. For later
126
- releases, `npx projectstore-codex@<version> upgrade --project "$PWD"`. Because
127
- Codex's plugin registry is user-global, ordinary uninstall removes only the
128
- project's agents block; `uninstall --global` is the explicit machine-wide
129
- removal. If `npx` answers `could not determine executable to run`, your
130
- registry (often a company mirror) serves a stale index that knows only the
131
- reserved `0.0.1` placeholder: name the version, and if that is not enough, the
132
- public registry: `npx --registry https://registry.npmjs.org
133
- projectstore-codex@<version> install --project "$PWD"` (the same holds for
134
- `projectstore-claude`). Codex is **experimental** until a live session has exercised every
135
- surface it installs; [`docs/harnesses.md`](./docs/harnesses.md) says what has
136
- been measured and what has not. From a checkout, the same npx path runs against
137
- a built tarball:
131
+ **Claude Code.** Setup registers the plugin from the npm package [`projectstore`](https://www.npmjs.com/package/projectstore) — one source package carrying every harness's manifest. It writes a small local marketplace of its own under your Claude home, then drives `claude plugin marketplace add` / `plugin install` **at local scope**, so the registration lands in this checkout's `.claude/settings.local.json` and nowhere else. The host CLI and a live session both rewrite the same settings files, so inside a Claude Code session the registration is deferred, and the plan says so: run setup from a terminal outside the session. When the checkout already loads ProjectStore from the git marketplace, setup asks whether to switch this project to the npm install or keep the git marketplace. A switch silences the git-marketplace copy for this checkout only (not globally), so the plugin does not load twice; `uninstall` turns it back on.
132
+
133
+ **Codex.** The Codex plugin ships in a package of its own; setup fetches it at setup's own version and plans Codex in the same plan as everything else. It stages a stable marketplace under `CODEX_HOME`, drives `codex plugin marketplace add` and `codex plugin add`, then reads the installation back and verifies its version and payload digest. Before it changes anything it asks Codex for that read-back (`codex plugin list --json`), so a Codex too old to answer stops the registration before it changes anything and tells you to upgrade Codex. Codex's plugin registry is user-global; the agents block in `AGENTS.md` stays project-local. Codex is **experimental** until a live session has exercised every surface it installs: [`docs/harnesses.md`](./docs/harnesses.md#codex) says what has been verified and what has not. A project can be worked from both agents: they share the binding in `.projectstore/`, and each keeps its own overlay and session state beside it ([running both over one project](./docs/harnesses.md#running-both-over-one-project)).
134
+
135
+ **The low-level verbs.** Setup composes verbs that also run on their own. One agent's install, with no questions about the project or the vault:
138
136
 
139
- ```sh
140
- npm run shells:build -- --only projectstore-codex --dev --out dist
141
- npx --package "./dist/projectstore-codex-$(node -p 'require("./package.json").version').tgz" projectstore-codex install --project "$PWD"
142
137
  ```
138
+ npx projectstore install --harness claude-code # shows the plan, asks at a terminal, then writes; without a terminal naming the harness is the confirmation — there is no --yes
139
+ ```
140
+
141
+ `plan` prints the same plan and writes nothing; `--verbose` adds every row's reasoning; `npx projectstore <verb> --help` lists a verb's options with examples. bun works the same on the packed bin.
143
142
 
144
- The package also carries a `bin`. Without a session — in CI, or in a shell — the same core answers token-free, with a `--json` envelope on every verb:
143
+ Without a session — in CI, or in a shell — the same core answers token-free, with a `--json` envelope on every verb:
145
144
 
146
145
  ```
147
146
  npx projectstore doctor --json
148
- npx projectstore install --harness claude-code # the low-level form the shell runs: shows the plan, asks at a terminal, then writes; without a terminal naming the harness is the confirmation — there is no --yes
149
147
  npx projectstore reconcile --write --only kanban
150
148
  ```
151
149
 
@@ -175,43 +173,76 @@ npx projectstore init ~/vaults/new-project --language ru
175
173
  npx projectstore scaffold --write
176
174
  ```
177
175
 
178
- `projectstore-claude`, `projectstore-codex` and `projectstore-opencode` are this package's per-harness shells — the core pinned and bundled, the harness fixed. The Claude Code and Codex shells are published at the core's version; Codex stays labelled experimental until a live run has exercised every surface it installs ([`docs/harnesses.md`](./docs/harnesses.md)). The opencode shell publishes after its plugin root is rendered. The other `projectstore-*` names are reserved placeholders pointing back here. One source package, one version, N tarballs.
176
+ `projectstore-claude`, `projectstore-codex` and `projectstore-opencode` are release artifacts: per-harness packages that carry the core, pinned at the same version and bundled, with the harness fixed. Nobody needs to type their names. Setup fetches the Codex one, which carries the Codex plugin; the Claude Code one is published at the core's version too; the opencode one publishes after its plugin root is rendered. The other `projectstore-*` names are reserved placeholders pointing back here. One source package, one version, N tarballs. How a release builds and publishes them, and how to run a checkout's own build: [`packaging/README.md`](./packaging/README.md).
179
177
  </details>
180
178
 
181
179
  ## Upgrading
182
180
 
183
- `/plugin update` (or auto-update) and a restart, then one command per project
184
- bound before 0.28. What an existing project sees afterwards, and why:
181
+ Installed with setup or from npm: from a terminal in your project, name the version you want to run (`latest` is the newest):
182
+
183
+ ```
184
+ npx projectstore@<version> upgrade
185
+ ```
186
+
187
+ It upgrades every agent the project uses — each one whose own directory (`.claude/`, `.codex/`) or `.projectstore/state/<id>/` is there — in one plan, and fetches the Codex plugin at the same version. `npx projectstore setup` converges a project the same way and asks its questions again. Installed from the git marketplace in a Claude Code session: `/plugin update` (or auto-update) and a restart.
188
+
189
+ A bare upgrade selects agents by those directories, so on Codex name it, which upgrades Codex even in a project where no Codex session has run yet:
190
+
191
+ ```
192
+ npx projectstore@<version> upgrade --harness codex
193
+ ```
194
+
195
+ With the global command, update it first, then run it in the project:
196
+
197
+ ```
198
+ npm install -g projectstore@latest
199
+ projectstore upgrade
200
+ ```
201
+
202
+ A project bound before 0.28 needs one more command. What an existing project sees afterwards, and why:
185
203
 
186
204
  - **The project's files move to `.projectstore/`.** `.claude/projectstore.json`
187
205
  and `.claude/.projectstore/` become `.projectstore/projectstore.json`,
188
206
  `.projectstore/harness/claude-code.json` and `.projectstore/state/`. Nothing
189
207
  breaks before you move them: every reader falls back to the old paths through
190
- 0.29, and the startup line names the command until the move is done. Close
191
- every Claude Code session in the project, run that command from a terminal,
192
- then restart. The command depends on how you installed:
193
- - **From the git marketplace** (every 0.27.x install): the installed copy's
194
- own `bin/projectstore.mjs`, with its path spelled out in the startup line —
195
- `node "<plugin cache>/bin/projectstore.mjs" upgrade --harness claude-code --no-register --project "$PWD"`.
196
- `--no-register` leaves your plugin registration as it is.
197
- - **From npm**: `npx projectstore-claude@<version> upgrade --no-register --project "$PWD"`.
198
-
199
- Both forms move only the project's files, so neither touches your plugin
200
- registration. The same run re-stamps the status-line launcher at its new path
201
- and re-registers the agents block, whose template is now v4. A plain
202
- `npx projectstore-claude upgrade` on a git-marketplace install does more: it
208
+ 0.30, and the startup line names the command until the move is done. Close
209
+ every Claude Code session in the project, run that command from a terminal in
210
+ the project, then restart. The command depends on how you installed. From the
211
+ git marketplace (every 0.27.x install), it is the installed copy's own
212
+ `bin/projectstore.mjs`, with its path spelled out in the startup line:
213
+
214
+ ```
215
+ node "<plugin cache>/bin/projectstore.mjs" upgrade --harness claude-code --no-register
216
+ ```
217
+
218
+ From npm:
219
+
220
+ ```
221
+ npx projectstore@<version> upgrade --harness claude-code --no-register
222
+ ```
223
+
224
+ `--no-register` leaves your plugin registration as it is: both forms move
225
+ only the project's files. The same run re-stamps the status-line launcher at
226
+ its new path and re-registers the agents block, whose template is now v4. An
227
+ upgrade without `--no-register` on a git-marketplace install does more: it
203
228
  also registers the plugin from npm for this checkout and turns the
204
229
  git-marketplace copy off here, so `/plugin update` stops reaching the
205
- checkout. The 0.28.0-rc.1 and rc.2 startup lines named that shell form
206
- (`npx projectstore-claude@<version> upgrade`, without `--no-register`), so on
207
- those, update first and run what the new startup line names. If it already
208
- happened,
209
- `npx projectstore-claude@<version> uninstall --surface plugin --project "$PWD"`
210
- (0.28.0 or later) turns the git-marketplace copy back on. That copy must be 0.28 or later — an
211
- older one reads a moved project as unbound — so update it first if it is not.
212
- Restart, then run
213
- `/projectstore:doctor --fix` in the new session, which re-stamps the status
214
- line against that copy.
230
+ checkout. The 0.28.0-rc.1 and rc.2 startup lines named that form, without
231
+ `--no-register`, so on those, update first and run what the new startup line
232
+ names. If it already happened, this turns the git-marketplace copy back on
233
+ (0.28.0 or later), from a terminal in the project:
234
+
235
+ ```
236
+ npx projectstore@<version> uninstall --harness claude-code --surface plugin
237
+ ```
238
+
239
+ That copy must be 0.28 or later — an older one reads a moved project as
240
+ unbound — so update it first if it is not. Restart, then in the new session,
241
+ to re-stamp the status line against that copy:
242
+
243
+ ```
244
+ /projectstore:doctor --fix
245
+ ```
215
246
  - **The status line keeps rendering.** A launcher written by an earlier version
216
247
  still works, but it carries no file stamp and its embedded fallback root is
217
248
  frozen at the old version; the move above re-stamps it. Nothing rewrites that
@@ -242,9 +273,9 @@ bound before 0.28. What an existing project sees afterwards, and why:
242
273
  move once more, and the move re-stamps the launcher. If a session already
243
274
  re-stamped the status line or re-registered the agents block before the move
244
275
  (rc.2's `/projectstore:doctor --fix` did both), 0.27.x reports a foreign
245
- status line and a v4 block and leaves both alone — unless you run its
246
- `/projectstore:agents register`, which rewrites the block; the status line
247
- still renders, and the move settles both.
276
+ status line and a v4 block and leaves both alone — unless you run
277
+ `/projectstore:agents register` in it, which rewrites the block; the status
278
+ line still renders, and the move settles both.
248
279
  - **Rolling back** to 0.27.x after the move: 0.27.x looks for its binding under
249
280
  `.claude/`, finds none and offers `bind`. Do not accept. A re-bind writes
250
281
  `.claude/projectstore.json` again, and 0.28's `install` and `upgrade` refuse
@@ -252,11 +283,11 @@ bound before 0.28. What an existing project sees afterwards, and why:
252
283
  `.claude/projectstore.json`, then run the command the startup line names
253
284
  once more: a 0.27.x session writes its welcome marker back under `.claude/`.
254
285
  - **Installed from npm?** Then `/plugin update` has nothing to fetch: the
255
- registration is refreshed by the package itself — from a terminal outside
256
- the session, `npx projectstore-claude@<version> upgrade --project "$PWD"`
257
- rewrites the local marketplace and runs the host's
258
- `plugin update` for this checkout. `/projectstore:doctor` says when the
259
- registration is behind the package, and names that command.
286
+ package itself refreshes the registration. The upgrade at the top of this
287
+ section, run from a terminal outside the session, rewrites the local
288
+ marketplace and runs the host's `plugin update` for this checkout.
289
+ `/projectstore:doctor` says when the registration is behind the package, and
290
+ names the command.
260
291
 
261
292
  ## When an agent starts a task, it can find its way
262
293
 
@@ -297,7 +328,25 @@ The deep dive — real session files, measured payloads, how every mechanism wor
297
328
 
298
329
  ## Uninstalling
299
330
 
300
- `/plugin uninstall projectstore@SmartAndPoint` for a Claude git-marketplace install; `npx projectstore-claude uninstall --project "$PWD"` for its npm registration. For Codex, `npx projectstore-codex uninstall --project "$PWD"` removes only project-owned wiring; add `--global` only to remove the user-global Codex plugin and marketplace. Your vault is yours — plain markdown, untouched. One leftover of a host-managed plugin path can be the agents block in `CLAUDE.md`/`AGENTS.md`; remove it with the harness's agents unregister skill, or delete everything between `<!-- projectstore:agents … -->` and `<!-- /projectstore:agents -->` by hand. A one-harness `uninstall` leaves a block that lives in `AGENTS.md`, because that file is read by other coding agents too. Claude Code's then removes the `CLAUDE.md` import when that file holds nothing else; Codex's keeps it, so Claude Code still sees the block. `uninstall --surface agents_block` removes the block as well. A bare core `npx projectstore uninstall --project "$PWD"`, with no `--harness`, covers every harness the project uses — each one whose own directory (`.claude/`, `.codex/`) or `.projectstore/state/<id>/` is there. Once every harness that can read the block's file is among them (for `AGENTS.md`, Claude Code and Codex), the block goes too, and the `CLAUDE.md` import with it unless your own text keeps both files.
331
+ From a terminal in your project:
332
+
333
+ ```
334
+ npx projectstore uninstall
335
+ ```
336
+
337
+ With no `--harness` it covers every agent the project uses — each one whose own directory (`.claude/`, `.codex/`) or `.projectstore/state/<id>/` is there — and removes what install wrote, and only that. For Codex that is the project-owned wiring: its plugin and marketplace are user-global, and removing them for every project is explicit:
338
+
339
+ ```
340
+ npx projectstore uninstall --harness codex --global
341
+ ```
342
+
343
+ A Claude Code install from the git marketplace is removed in the session:
344
+
345
+ ```
346
+ /plugin uninstall projectstore@SmartAndPoint
347
+ ```
348
+
349
+ Your vault is yours — plain markdown, untouched. One leftover of a host-managed plugin path can be the agents block in `CLAUDE.md`/`AGENTS.md`; remove it with the harness's agents unregister skill, or delete everything between `<!-- projectstore:agents … -->` and `<!-- /projectstore:agents -->` by hand. A one-harness `uninstall`, with `--harness <id>`, leaves a block that lives in `AGENTS.md`, because that file is read by other coding agents too. Claude Code's then removes the `CLAUDE.md` import when that file holds nothing else; Codex's keeps it, so Claude Code still sees the block. `uninstall --surface agents_block` removes the block as well. Once every harness that can read the block's file is among those uninstalled (for `AGENTS.md`, Claude Code and Codex), the block goes too, and the `CLAUDE.md` import with it unless your own text keeps both files.
301
350
 
302
351
  ## Extending
303
352
 
@@ -307,6 +356,33 @@ See [`docs/extending.md`](./docs/extending.md) for adding layouts, templates, an
307
356
 
308
357
  Issues and discussions: https://github.com/SmartAndPoint/ProjectStore/issues. PRs welcome — adding a layout is a good first contribution (see `scaffold/layouts/engineering.json` for the format).
309
358
 
359
+ The published package has no dependencies; the linter and the formatter are dev-only, pinned in `package-lock.json`. Every pull request runs the tests, ESLint and Prettier:
360
+
361
+ ```sh
362
+ npm test # Node 20+, no install needed
363
+ npm ci # once, for the lint tools (Node 20.19+, 22.13+ or 24+)
364
+ npm run lint
365
+ npm run format # rewrites; npm run format:check only reports
366
+ ```
367
+
368
+ One formatting-only commit is listed in `.git-blame-ignore-revs`. GitHub skips it in blame by itself; a local clone needs this once:
369
+
370
+ ```sh
371
+ git config blame.ignoreRevsFile .git-blame-ignore-revs
372
+ ```
373
+
374
+ A branch opened before that commit rebases in two steps, so that the lint fixes before it are kept. First onto the commit before it, resolving real conflicts as usual:
375
+
376
+ ```sh
377
+ git rebase <the commit before it>
378
+ ```
379
+
380
+ Then onto the formatting commit itself, where every conflict is formatting only: take your side, format the file with `npx prettier --write <file>` and `git add` it, then continue.
381
+
382
+ ```sh
383
+ git rebase --onto <it> <the commit before it>
384
+ ```
385
+
310
386
  ## License
311
387
 
312
388
  MIT — see [`LICENSE`](./LICENSE).
@@ -3,7 +3,7 @@ description: Bind this project to an Obsidian vault (or any markdown directory)
3
3
  argument-hint: <vault-path> | --inherit [--layout engineering] [--lang en|ru|es|de|fr|zh]
4
4
  ---
5
5
 
6
- You are binding the current project to a markdown vault for projectstore. The config is written by the core's `bind` / `init` verbs (roadmap A8); this interview decides the values, previews them, and asks — it never writes `projectstore.json` itself, except on the inherit path (step 0a), which copies the parent's file verbatim, and the two later stamps in steps 11–12 (`autoupdate_asked`, `statusline`), which `Edit` the file the verb wrote. The interview's `--lang` is the verb's `--language`.
6
+ You are binding the current project to a markdown vault for projectstore. The config is written by the core's `bind` / `init` verbs (roadmap A8); this interview decides the values, previews them, and asks — it never writes `projectstore.json` itself, except on the inherit path (step 0a), which copies the parent's file verbatim, and the one later stamp in step 11 (`statusline`), which `Edit`s the file the verb wrote. The interview's `--lang` is the verb's `--language`.
7
7
 
8
8
  Parse `$ARGUMENTS`:
9
9
  - First positional arg: vault path. Expand `~` if present.
@@ -48,10 +48,10 @@ Steps:
48
48
 
49
49
  It prints `{state, worktree, mainCheckout, vaultPath}` and writes nothing.
50
50
  - `state` is **not** `inheritable` → say why in one line (not a worktree, its parent is unbound too, or git could not answer) and fall through to step 1, which needs a vault path; if none was given, ask for one.
51
- - `state` is `inheritable` → read the parent's `<mainCheckout>/.projectstore/projectstore.json` (or, in a checkout not yet migrated, the legacy `<mainCheckout>/.claude/projectstore.json`), show it **verbatim as a code block** — but for a `channel_switch` key, which is left out (below) — and ask via AskUserQuestion: "Adopt the binding of `<mainCheckout>` (vault `<vaultPath>`)?" — Yes / No.
52
- - On **Yes**: Write that JSON verbatim, without `channel_switch`, to `<project>/.projectstore/projectstore.json`, **and write `<project>/.projectstore/.gitignore` beside it** with the two lines `projectstore.json` and `state/` under a comment saying they are machine-local (the verb writes them itself on every other path; this one bypasses the verb, and without them the worktree commits an absolute vault path into the index it shares with its parent). If that file already exists, add any missing line and leave the rest — it is line-merged. Then **jump straight to step 10** (the summary). Steps 1–9 and 11–12 are decisions the parent already made and the copied config already carries — layout, language, statusline, agent models, auto-update. Do not re-ask them, and do not scaffold: the vault exists and is shared.
51
+ - `state` is `inheritable` → read the parent's `<mainCheckout>/.projectstore/projectstore.json` (or, in a checkout not yet migrated, the legacy `<mainCheckout>/.claude/projectstore.json`), show it **verbatim as a code block** — but for the `channel_switch` and `channel_keep` keys, which are left out (below) — and ask via AskUserQuestion: "Adopt the binding of `<mainCheckout>` (vault `<vaultPath>`)?" — Yes / No.
52
+ - On **Yes**: Write that JSON verbatim, without `channel_switch` and `channel_keep`, to `<project>/.projectstore/projectstore.json`, **and write `<project>/.projectstore/.gitignore` beside it** with the two lines `projectstore.json` and `state/` under a comment saying they are machine-local (the verb writes them itself on every other path; this one bypasses the verb, and without them the worktree commits an absolute vault path into the index it shares with its parent). If that file already exists, add any missing line and leave the rest — it is line-merged. Then **jump straight to step 10** (the summary). Steps 1–9 and 11 are decisions the parent already made and the copied config already carries — layout, language, statusline, agent models. Do not re-ask them, and do not scaffold: the vault exists and is shared.
53
53
  - Copy the **binding only** (`projectstore.json`). Never copy `.projectstore/state/` — per-session state belonging to the other checkout — and never `harness/`: the overlays are committed and arrive from git.
54
- - **Never copy `channel_switch`.** It records that the parent checkout was switched to the npm install — a machine-local fact of that checkout, not of the binding it shares. Every other key is copied verbatim.
54
+ - **Never copy `channel_switch` or `channel_keep`.** They record which channel the parent checkout chose — switched to the npm install, or kept on the git marketplace — a machine-local fact of that checkout's own registry rows, not of the binding it shares. Every other key is copied verbatim.
55
55
  - Do not add a provenance key to the config. The parent is resolvable from git at any time; a key would be a second source of truth for the same fact.
56
56
 
57
57
  1. **Validate the vault path** read-only first: `ls -A "<path>"` (the verb has no dry run — running it on a fresh project would write the config before step 4's approval). If it does not exist, or exists and is empty, ask the user (via AskUserQuestion) whether to create the vault there; on Yes, step 5 runs `init` instead of `bind`. `init` creates the whole vault and binds: the directory (unless it is there and empty), its git repository with no commit, and the layout's folders and READMEs. Never `mkdir` it yourself. A directory that already holds files is bound with `bind`; `init` would bind it too, but never scaffolds or `git init`s inside it.
@@ -81,7 +81,7 @@ Steps:
81
81
  node "${CLAUDE_PLUGIN_ROOT}/bin/projectstore.mjs" bind "<vault-path>" [--layout <name>] [--language <code>] [--rebind]
82
82
  ```
83
83
 
84
- `init "<vault-path>" …` instead when step 1 chose to create the vault — it creates the whole vault, so step 7 has nothing to offer after it; `--rebind` only when step 0 ended on **Replace bind**. Naming the vault is the verb's confirmation (there is no `--yes`); the interview's AskUserQuestion in step 4 is the in-session gate. Print the verb's output. A non-zero exit is a refusal or a usage error — relay it and stop — except an `init` whose output reports `git init failed` or `Scaffold failed`: the binding is written, so relay the remedy line it prints and continue. Steps 11 and 12 below `Edit` the file this step wrote; keep them after it.
84
+ `init "<vault-path>" …` instead when step 1 chose to create the vault — it creates the whole vault, so step 7 has nothing to offer after it; `--rebind` only when step 0 ended on **Replace bind**. Naming the vault is the verb's confirmation (there is no `--yes`); the interview's AskUserQuestion in step 4 is the in-session gate. Print the verb's output. A non-zero exit is a refusal or a usage error — relay it and stop — except an `init` whose output reports `git init failed` or `Scaffold failed`: the binding is written, so relay the remedy line it prints and continue. Step 11 below `Edit`s the file this step wrote; keep it after it.
85
85
 
86
86
  6. **Check `.gitignore`**: read `<project>/.gitignore` if it exists. Our own files are self-ignored inside `.projectstore/` — the verb writes that `.gitignore` itself, carrying `projectstore.json` and `state/`, with `harness/` committed on purpose (the layout ADR); on the inherit path of step 0a, which bypasses the verb, you wrote both by hand. Unless `.claude/` is ignored wholesale, the one machine-specific entry left is the host's `.claude/settings.local.json`. If it is missing, offer (AskUserQuestion) to append it. If the user declines, skip silently.
87
87
 
@@ -115,18 +115,7 @@ Steps:
115
115
 
116
116
  10. **Print summary**: confirm the bind, list the layout's folders, suggest next commands (`/projectstore:status`, `/projectstore:adr "<first decision>"`, `/projectstore:epic <ID> "<title>"`).
117
117
 
118
- 11. **Auto-update reminder** (v0.7+, only on first successful bind in this project): After Step 5 (config write), check whether the newly-written config has `autoupdate_asked: true`. If not, ask the user via AskUserQuestion:
119
-
120
- > "Claude Code does not auto-update third-party marketplaces by default. Want to enable auto-update for the SmartAndPoint marketplace so you'll be notified about future projectstore releases?"
121
-
122
- Options:
123
- - **Yes, show me how** (Recommended) — respond with: "Open `/plugin` → **Marketplaces** tab → **SmartAndPoint** → toggle **auto-update** on. New releases (v0.7+) will be detected at Claude Code startup; you'll need to run `/reload-plugins` after the notification to activate them."
124
- - **No, I'll handle it manually** — respond with: "OK. To pull the latest version at any time, run `/plugin marketplace update SmartAndPoint`, then `/reload-plugins`."
125
- - **Already enabled** — respond with: "Great. New releases will be detected at the next Claude Code startup."
126
-
127
- After the question is answered (regardless of choice), Edit `<project>/.projectstore/projectstore.json` to add `"autoupdate_asked": true` to the JSON object. This guarantees we ask only once per project.
128
-
129
- 12. **Status line offer** (v0.13, ADR-006 — the final step, language is known by now): read `${CLAUDE_PLUGIN_ROOT}/templates/<lang>/strings.json` (fall back to `en`) and the plugin version, then show the fully rendered example:
118
+ 11. **Status line offer** (v0.13, ADR-006 — the final step, language is known by now): read `${CLAUDE_PLUGIN_ROOT}/templates/<lang>/strings.json` (fall back to `en`) and the plugin version, then show the fully rendered example:
130
119
 
131
120
  > `[PS#<version>] 📚 <statusline_example_epic> › <statusline_example_story> (in-progress)`
132
121
 
@@ -66,20 +66,25 @@ You are running projectstore diagnostics (ADR-005: umbrella doctor).
66
66
  The verbs refuse it in code; this clause is the belt.
67
67
  - `version-drift` → report only: name both versions and where each was
68
68
  read; the fix is the host's update path (`/plugin update` for a git-marketplace
69
- copy; for the npm registration, the `projectstore-claude` shell's `upgrade`
70
- from a terminal — the `plugin-registration` finding spells the command),
69
+ copy; for the npm registration, the package's `upgrade` from a terminal
70
+ in the project — the `plugin-registration` finding spells the command),
71
71
  not ours.
72
72
  - `layout-legacy` (warn; the startup line carries it as an offer) → the project
73
73
  still holds the pre-0.28 layout (`.claude/projectstore.json`,
74
- `.claude/.projectstore/` — legacy, read through 0.29). The migration is one
74
+ `.claude/.projectstore/` — legacy, read through 0.30). The migration is one
75
75
  previewed `layout` item of `upgrade`, run **from a terminal outside this
76
76
  session** (it moves files this session reads and writes; the verb defers
77
77
  inside one). The finding names the form for the channel this plugin was
78
78
  installed through: the installed copy's own `bin/projectstore.mjs` for a
79
- git-marketplace install or a checkout, the `projectstore-claude` shell for
80
- the npm registration. Relay the finding's command verbatim and never
81
- substitute the other form — the shell, run for a git-marketplace install,
82
- would also move this checkout to the npm channel. When the finding carries
79
+ git-marketplace install or a checkout, the package's `upgrade` for the npm
80
+ registration. Relay the finding's command verbatim, with the directory its
81
+ words name, and never substitute the other form or drop its
82
+ `--no-register`. Both forms carry that flag, so neither changes the
83
+ channel: the named form runs the copy this project loads, so the move
84
+ re-stamps the launcher that copy renders, while the other form runs a
85
+ different copy. The package's `upgrade` without `--no-register` would
86
+ register the npm copy and turn a git-marketplace copy off for this
87
+ checkout. When the finding carries
83
88
  advice instead of a command — the installed copy predates the move, or
84
89
  predates `--no-register` — relay the advice and never compose a command
85
90
  yourself. Never move the files yourself. While this finding is in the report, its command is also the one
@@ -5,7 +5,7 @@ argument-hint: "on | off | status"
5
5
 
6
6
  You are toggling the projectstore status line for THIS project. When enabled, `install-harness.mjs` points the project's `.claude/settings.local.json` at a launcher it writes at `.projectstore/state/claude-code/statusline.mjs`. That path carries no version, so it never goes stale: the launcher resolves the *currently installed* plugin on every render, and an update is reflected on the spot instead of one restart later. (A dev checkout or `--plugin-dir` root is wired straight to its `scripts/statusline.mjs` — those paths have no version to drift.) The line renders `[PS#<version>] 📚 <epic> › <story> (<status>)` **composed above** any existing HUD (e.g. oh-my-claudecode), never replacing it. While this session's band above the prompt is drawing (`/projectstore:bar`), the line gives way to it — your base HUD stays — and it comes back within 30 s of the band stopping.
7
7
 
8
- Resolution is **per-session with zero cross-session and zero vault reads** (ADR-006): the 📚 segment comes from this session's pointer (`.projectstore/state/sessions/<session_id>.json`, maintained by the PreToolUse hook); a fresh session shows an explicit localized cold-start line ("No epic or story in this session yet" / «Эпик и стори ещё не в работе в этой сессии») — never a silent blank; a corrupt pointer shows an error-marked string. Strings localize via `templates/<lang>/strings.json` (en fallback). The version badge is controlled by `statusline.show_version` (default true).
8
+ Resolution is **per-session with zero cross-session and zero vault reads** (ADR-006): the 📚 segment comes from this session's pointer (`.projectstore/state/sessions/<session_id>.json`, maintained by the tool hooks — a write's patch after the write — by `story close`, and at session start; a done, closed or parked story leaves the segment); a fresh session shows an explicit localized cold-start line ("No epic or story in this session yet" / «Эпик и стори ещё не в работе в этой сессии») — never a silent blank; a corrupt pointer shows an error-marked string. Strings localize via `templates/<lang>/strings.json` (en fallback). The version badge is controlled by `statusline.show_version` (default true).
9
9
 
10
10
  This command flips the flag in `.projectstore/projectstore.json` and then runs the install verb, which writes `settings.local.json` and the launcher behind a preview. The SessionStart hook only refreshes an entry that is already ours and removes it when the flag is off — it never creates one.
11
11
 
@@ -92,11 +92,11 @@ the two cannot collide).
92
92
  <baseline-path>`), the derived targets (`kanban`, plus `indexes=<epic
93
93
  folder>` when status changed), and the doctor pre-state line. On a clean
94
94
  report (`verbatim: true`, `stopped_at: null`, doctor no worse than the
95
- pre-state) skip steps 6-6b — the clerk's report is the write evidence. On a
95
+ pre-state) skip steps 6-6b and run step 6c — the clerk's report is the write evidence. On a
96
96
  stopped report: fix what diverged, then re-delegate (the resume rule: after
97
97
  the copy, the ceremony restarts at reconcile, not at the race gate) or
98
98
  finish the remaining steps yourself (the copy is idempotent).
99
- - No clerk available → perform steps 6-6b yourself. There is no fallback
99
+ - No clerk available → perform steps 6-6c yourself. There is no fallback
100
100
  agent: a general-purpose writer is an unpinned procedure.
101
101
 
102
102
  6. **On Yes** (undelegated path): Write the full file. On a `plan`, finish by
@@ -111,3 +111,16 @@ the two cannot collide).
111
111
  — a close is not done while doctor got worse. Then suggest the reviewer's
112
112
  proposed `code_refs` via `/projectstore:codemap set` (the reviewer computes it
113
113
  from `scripts/diff-refs.mjs --since <started_at>`).
114
+
115
+ 6c. **(close only, both paths) Refresh this session's story**, here in the
116
+ main thread, after the clerk's clean report or after 6b:
117
+
118
+ ```bash
119
+ node "${CLAUDE_PLUGIN_ROOT}/bin/projectstore.mjs" session refresh "<story-path>" --json --project "${CLAUDE_PROJECT_DIR}"
120
+ ```
121
+
122
+ `<story-path>` is the absolute `path` the compute script returned in
123
+ step 2. The copy went through Bash, which no hook sees, so without this the
124
+ session's band and status line keep naming the closed story. The core finds
125
+ the session itself; with none it writes nothing and exits 0. A non-zero
126
+ exit is reported and never undoes the close.
@@ -49,12 +49,17 @@ vault-side layout or template override):
49
49
  4. **Checklist entry** — `scaffold/checklists.json`, consumed by
50
50
  `/projectstore:review` and the `projectstore-peer-reviewer` skill. English-only by design.
51
51
 
52
- 5. **Command prompt** — `commands/<kind>.md`, a prompt (not code) that calls
53
- `node "${CLAUDE_PLUGIN_ROOT}/scripts/draft.mjs" <kind> "$ARGUMENTS"`, previews,
54
- and gates every write behind AskUserQuestion. Copy `commands/research.md`
55
- for a plain kind, `commands/adr.md` for one that renders the draft's
56
- `collision`/`warnings` fields and updates an index, `commands/spec.md`
57
- for one with status transitions.
52
+ 5. **Command prompt** — `commands/<kind>.md`, a prompt (not code). It renders
53
+ the draft with the line below, previews it, and gates every write behind
54
+ AskUserQuestion:
55
+
56
+ ```
57
+ node "${CLAUDE_PLUGIN_ROOT}/scripts/draft.mjs" <kind> "$ARGUMENTS"
58
+ ```
59
+
60
+ Copy `commands/research.md` for a plain kind, `commands/adr.md` for one
61
+ that renders the draft's `collision`/`warnings` fields and updates an
62
+ index, `commands/spec.md` for one with status transitions.
58
63
 
59
64
  6. **Folder strings** — `templates/<lang>/strings.json` → `folders.<kind>`,
60
65
  a `name` and a one-line `description`, in **every** bundled language's