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.
- package/README.md +13 -12
- package/bin/projectstore-claude.mjs +2 -2
- package/node_modules/projectstore/.claude-plugin/marketplace.json +1 -1
- package/node_modules/projectstore/.claude-plugin/plugin.json +1 -1
- package/node_modules/projectstore/README.md +153 -77
- package/node_modules/projectstore/commands/bind.md +6 -17
- package/node_modules/projectstore/commands/doctor.md +12 -7
- package/node_modules/projectstore/commands/statusline.md +1 -1
- package/node_modules/projectstore/commands/story.md +15 -2
- package/node_modules/projectstore/docs/extending.md +11 -6
- package/node_modules/projectstore/docs/getting-started.md +21 -1
- package/node_modules/projectstore/docs/harnesses.md +13 -10
- package/node_modules/projectstore/docs/how-it-works.md +6 -4
- package/node_modules/projectstore/harnesses/claude-code.json +16 -15
- package/node_modules/projectstore/harnesses/codex.json +12 -13
- package/node_modules/projectstore/hooks/band.tsx +48 -20
- package/node_modules/projectstore/hooks/pre-compact.mjs +7 -10
- package/node_modules/projectstore/hooks/session-rules.mjs +14 -8
- package/node_modules/projectstore/hooks/session-start.mjs +50 -18
- package/node_modules/projectstore/hooks/session-stop.mjs +8 -6
- package/node_modules/projectstore/package.json +11 -2
- package/node_modules/projectstore/scripts/band-shared.mjs +141 -24
- package/node_modules/projectstore/scripts/band.mjs +72 -21
- package/node_modules/projectstore/scripts/binding.mjs +616 -85
- package/node_modules/projectstore/scripts/build-adapters.mjs +73 -29
- package/node_modules/projectstore/scripts/cli.mjs +1015 -185
- package/node_modules/projectstore/scripts/codemap.mjs +22 -7
- package/node_modules/projectstore/scripts/convergence.mjs +253 -83
- package/node_modules/projectstore/scripts/diff-refs.mjs +14 -8
- package/node_modules/projectstore/scripts/doctor-report.mjs +91 -23
- package/node_modules/projectstore/scripts/doctor.mjs +1317 -371
- package/node_modules/projectstore/scripts/draft.mjs +5 -2
- package/node_modules/projectstore/scripts/fetch-shell.mjs +188 -39
- package/node_modules/projectstore/scripts/graph.mjs +19 -13
- package/node_modules/projectstore/scripts/harness.mjs +123 -48
- package/node_modules/projectstore/scripts/install-harness.mjs +3532 -618
- package/node_modules/projectstore/scripts/kanban.mjs +2 -1
- package/node_modules/projectstore/scripts/lib.mjs +694 -159
- package/node_modules/projectstore/scripts/mcp.mjs +386 -105
- package/node_modules/projectstore/scripts/portable-registration.mjs +224 -51
- package/node_modules/projectstore/scripts/provenance.mjs +26 -10
- package/node_modules/projectstore/scripts/query.mjs +378 -80
- package/node_modules/projectstore/scripts/reconcile.mjs +55 -18
- package/node_modules/projectstore/scripts/run-host.mjs +62 -17
- package/node_modules/projectstore/scripts/scaffold.mjs +89 -28
- package/node_modules/projectstore/scripts/setup.mjs +987 -0
- package/node_modules/projectstore/scripts/stages.mjs +5 -1
- package/node_modules/projectstore/scripts/statusline-launcher.mjs +36 -11
- package/node_modules/projectstore/scripts/statusline.mjs +32 -14
- package/node_modules/projectstore/scripts/story-section.mjs +39 -17
- package/node_modules/projectstore/scripts/surfaces.mjs +416 -95
- package/node_modules/projectstore/scripts/term.mjs +382 -97
- package/node_modules/projectstore/scripts/tokens.mjs +106 -28
- package/node_modules/projectstore/scripts/touch-session.mjs +109 -70
- package/node_modules/projectstore/scripts/version-guard.mjs +74 -27
- package/node_modules/projectstore/scripts/worktree.mjs +16 -5
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,25 +1,26 @@
|
|
|
1
1
|
# projectstore-claude
|
|
2
2
|
|
|
3
|
-
|
|
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
|
|
10
|
+
npx projectstore setup
|
|
7
11
|
```
|
|
8
12
|
|
|
9
|
-
|
|
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
|
-
|
|
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
|
-
|
|
17
|
+
```sh
|
|
18
|
+
npx projectstore@<version> upgrade
|
|
19
|
+
```
|
|
19
20
|
|
|
20
|
-
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
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
|
[](https://github.com/SmartAndPoint/ProjectStore/releases) [](./LICENSE) [](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
|
|
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
|
|
78
|
+
## Install
|
|
79
79
|
|
|
80
|
-
|
|
80
|
+
From a terminal in your project:
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
```
|
|
83
|
+
npx projectstore setup
|
|
84
|
+
```
|
|
83
85
|
|
|
84
|
-
|
|
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
|
-
|
|
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
|
-
|
|
93
|
+
npm install -g projectstore
|
|
94
|
+
projectstore setup
|
|
90
95
|
```
|
|
91
96
|
|
|
92
|
-
|
|
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
|
-
|
|
95
|
-
|
|
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
|
|
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
|
-
|
|
125
|
+
claude --plugin-dir ./ProjectStore
|
|
112
126
|
```
|
|
113
127
|
|
|
114
|
-
|
|
128
|
+
<details>
|
|
129
|
+
<summary>What setup does for each agent, the low-level verbs, the CLI and MCP</summary>
|
|
115
130
|
|
|
116
|
-
**
|
|
117
|
-
|
|
118
|
-
plugin
|
|
119
|
-
|
|
120
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
184
|
-
|
|
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.
|
|
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
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
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
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
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
|
|
246
|
-
`/projectstore:agents register
|
|
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
|
-
|
|
256
|
-
the session,
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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`.**
|
|
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.
|
|
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. **
|
|
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
|
|
70
|
-
|
|
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.
|
|
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 `
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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
|
|
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-
|
|
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)
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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
|