projectstore-claude 0.28.0 โ†’ 0.28.2

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.
@@ -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.28.0",
15
+ "version": "0.28.2",
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.28.0",
4
+ "version": "0.28.2",
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).
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.
8
8
 
9
9
  ---
10
10
 
@@ -66,6 +66,14 @@ Open Claude Code in your project and say:
66
66
 
67
67
  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.
68
68
 
69
+ **On Codex**, run one command from a terminal in your project:
70
+
71
+ ```
72
+ npx projectstore-codex install --project "$PWD"
73
+ ```
74
+
75
+ 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)).
76
+
69
77
  <details>
70
78
  <summary>Prefer to type it yourself?</summary>
71
79
 
@@ -88,28 +96,26 @@ npx projectstore-claude install --project "$PWD"
88
96
 
89
97
  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. Every host command is printed before it runs; naming the harness is the confirmation. 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.
90
98
 
91
- **Codex uses its own rendered plugin root and the same one-command shape.**
92
- Codex support is **experimental** (see [`docs/harnesses.md`](./docs/harnesses.md)
93
- for what has been measured and what has not), and its shell is not published
94
- yet. From this checkout, exercise the exact npx path against the built tarball:
99
+ **Codex has its own shell with the same one-command shape:**
100
+ `npx projectstore-codex install --project "$PWD"`. It carries a Codex
101
+ plugin manifest, namespaced workflow and role skills, lifecycle hooks, and
102
+ the exact bundled core. It stages a stable marketplace under `CODEX_HOME`,
103
+ drives `codex plugin marketplace add` and `codex plugin add`, then reads the
104
+ installation back and verifies its version and payload digest. Restart Codex,
105
+ approve the hooks, and run `$projectstore-bind <vault-path>`. For later
106
+ releases, `npx projectstore-codex@<version> upgrade --project "$PWD"`. Because
107
+ Codex's plugin registry is user-global, ordinary uninstall removes only the
108
+ project's agents block; `uninstall --global` is the explicit machine-wide
109
+ removal. Codex is **experimental** until a live session has exercised every
110
+ surface it installs; [`docs/harnesses.md`](./docs/harnesses.md) says what has
111
+ been measured and what has not. From a checkout, the same npx path runs against
112
+ a built tarball:
95
113
 
96
114
  ```sh
97
115
  npm run shells:build -- --only projectstore-codex --dev --out dist
98
116
  npx --package "./dist/projectstore-codex-$(node -p 'require("./package.json").version').tgz" projectstore-codex install --project "$PWD"
99
117
  ```
100
118
 
101
- The Codex shell carries a canonical portable manifest, namespaced workflow and
102
- role skills, lifecycle hooks, and the exact bundled core. It stages a stable
103
- marketplace under `CODEX_HOME`, drives `codex plugin marketplace add` and
104
- `codex plugin add`, then reads the installation back and verifies its version
105
- and payload digest. Restart Codex, approve the hooks, and run
106
- `$projectstore-bind <vault-path>`. After the first explicit npm publication,
107
- the shorter command is
108
- `npx projectstore-codex@<version> install --project "$PWD"`; use its `upgrade`
109
- verb for later releases. Because Codex's
110
- plugin registry is user-global, ordinary uninstall removes only the project's
111
- agents block; `uninstall --global` is the explicit machine-wide removal.
112
-
113
119
  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:
114
120
 
115
121
  ```
@@ -141,7 +147,7 @@ npx projectstore bind ~/vaults/my-project
141
147
  npx projectstore init ~/vaults/new-project --language ru
142
148
  ```
143
149
 
144
- `projectstore-claude`, `projectstore-codex` and `projectstore-opencode` are this package's per-harness shells โ€” the core pinned and bundled, the harness fixed. Codex's shell is experimental and stays private until a live run has exercised every surface it installs, from an installed release ([`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.
150
+ `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.
145
151
  </details>
146
152
 
147
153
  ## Upgrading
@@ -23,8 +23,10 @@ and the measurements in the manifest came from that run.
23
23
  **experimental** means `verified` is `null`. Every field that was not measured
24
24
  is absent or `null` rather than guessed. It is enough to run on; it is not enough
25
25
  to promise. An experimental harness is never the source layout. A generated
26
- adapter may exist while it is experimental, but its distribution shell stays
27
- private until the complete built artifact passes the live gate.
26
+ adapter may exist while it is experimental. Its distribution shell may
27
+ publish before the live run that sets `verified`, but only by the maintainer's
28
+ decision (Codex's does, from 0.28.1); the label stays experimental until that
29
+ run.
28
30
 
29
31
  The label is not prose. It is derived from the manifest, and
30
32
  `tests/portability.test.mjs` fails if this table and `verified` disagree.
@@ -43,14 +45,15 @@ model names and those are harness-specific โ€” is
43
45
 
44
46
  ## Codex
45
47
 
46
- Experimental, measured on `codex-cli 0.153.4`. The initial spike captured 759
48
+ Experimental, measured on `codex-cli 0.153.4` and, for hook loading, 0.160.0.
49
+ The initial spike captured 759
47
50
  hook firings. The 2026-09-30 gate then built the npm shell from a packed core,
48
51
  passed Codex's plugin validator, installed and upgraded it through an isolated
49
52
  `CODEX_HOME`, verified the materialised cache by version and digest, and loaded
50
- `$projectstore-status` in a fresh Codex session. The validator (the
53
+ the `projectstore-status` skill in a fresh Codex session. The validator (the
51
54
  plugin-creator skill's `validate_plugin.py`) reads only
52
- `.codex-plugin/plugin.json`, so the canonical root `plugin.json` has not been
53
- validated.
55
+ `.codex-plugin/plugin.json`, which from 0.28.2 is the shell's only manifest
56
+ (below).
54
57
 
55
58
  That run exercised one skill, not every installed surface, so `verified` stays
56
59
  `null`. The hooks are the reason it matters. On 2026-10-03 the first real
@@ -61,7 +64,8 @@ was all the user saw. The core had taken the shell's root for its own. That is
61
64
  fixed, and the suite now runs every rendered hook from the built shell. A live
62
65
  Codex session firing them from an installed release is still owed.
63
66
 
64
- How 0.153.4 starts a hook was read from its source, not measured: under the
67
+ How 0.153.4 starts a hook was read from its source; on 0.160.0 it was seen
68
+ once, with the hook's `$0` reading `/bin/zsh` and `node` found. Under the
65
69
  session's shell as `<shell> -c`, with the environment the Codex process had when
66
70
  it built the session's hooks. `$SHELL -lc` (or `/bin/sh -lc`) is the fallback
67
71
  when the hooks are built without exactly one ready local environment. So a hook
@@ -70,35 +74,48 @@ zsh reads `.zshenv` for a `-c` command, not `.zprofile` or `.zshrc`, so a Codex
70
74
  not started from a terminal can miss a `node` that only `.zprofile` puts on
71
75
  `PATH`.
72
76
 
73
- The shell is not published. Build it and install the tarball through npx from
74
- this checkout:
77
+ The shell is published as `projectstore-codex` from 0.28.1, ahead of that live
78
+ run, by the maintainer's decision:
79
+
80
+ ```sh
81
+ npx projectstore-codex install --project "$PWD"
82
+ ```
83
+
84
+ For later releases, `npx projectstore-codex@<version> upgrade --project "$PWD"`.
85
+ Installation is user-global because Codex stores marketplace registrations and
86
+ plugin caches in `CODEX_HOME`; the agents block in `AGENTS.md` remains
87
+ project-local. Ordinary uninstall leaves the global plugin in place; add
88
+ `--global` only when you mean to remove it for every project. From this
89
+ checkout, the same flow runs against a built tarball:
75
90
 
76
91
  ```sh
77
92
  npm run shells:build -- --only projectstore-codex --dev --out dist
78
93
  npx --package "./dist/projectstore-codex-$(node -p 'require("./package.json").version').tgz" projectstore-codex install --project "$PWD"
79
94
  ```
80
95
 
81
- The shell package is release-gated until its first npm publication. From this
82
- repository, the same flow is exercised against the packed tarball. Installation
83
- is user-global because Codex stores marketplace registrations and plugin caches
84
- in `CODEX_HOME`; the agents block in `AGENTS.md` remains project-local. After
85
- the first explicit npm publication, the shorter registry form is
86
- `npx projectstore-codex@<version> install --project "$PWD"` (or `upgrade`). Ordinary
87
- uninstall leaves the global plugin in place; add `--global` only when you mean
88
- to remove it for every project.
89
-
90
96
  What is known, and how:
91
97
 
92
- - **Hooks are rendered; their live firing from an installed release is not
93
- yet observed.** The canonical portable `plugin.json` selects
94
- `./hooks/hooks.json` through `extensions.com.openai`; the compatibility
95
- `.codex-plugin/plugin.json` stays inside the current ingestion schema. Five
98
+ - **Hooks load from Codex's default file, so the shell carries no root
99
+ `plugin.json`.** `.codex-plugin/plugin.json` is its only manifest and names
100
+ no hooks, so Codex falls back to `hooks/hooks.json`. 0.28.1, and every
101
+ build from a checkout since rc.3, also carried a root Agent Plugins
102
+ `plugin.json`, with the hooks under `extensions.com.openai`. Codex picks
103
+ that manifest first, and since openai/codex#37027 (merged 2026-08-05; in
104
+ `codex-cli` 0.153.4 and 0.160.0 alike) it loads no hooks from that format.
105
+ So no hook of ours loaded from those builds on any Codex measured here
106
+ (0.153.4, 0.160.0). On the maintainer's machine
107
+ on 2026-10-04, `/hooks` listed none of ours; with that file renamed away in
108
+ the installed cache, it listed all six, and the app server's `hooks/list`
109
+ gives 0 for 0.28.1's root and 6 for 0.28.2's. Five
96
110
  events: `SessionStart`, `PreToolUse`, `PostToolUse`, `Stop`, `PreCompact`.
97
111
  Of the 759 captured firings, 757 came from the earlier inline form, across
98
112
  `SessionStart`, `UserPromptSubmit`, `PreToolUse`, `PostToolUse` and `Stop`,
99
113
  and 2 from a file-site `hooks/hooks.json` with an absolute `node` path.
100
- `PreCompact` has never been observed firing on Codex, and neither has the
101
- `${PLUGIN_ROOT}` form selected through `extensions.com.openai`. The hook process
114
+ That live `codex-cli` 0.160.0 session ran on a hand-edited 0.28.1 cache, not
115
+ an installed release. Our SessionStart and PreCompact were observed in it. A
116
+ throwaway recorder saw PreToolUse, PostToolUse and Stop fire, but ours on
117
+ PostToolUse, matched to `apply_patch`, still awaits a write. SessionStart ran
118
+ on the session's first message, not when the window opened. The hook process
102
119
  receives `PLUGIN_ROOT` in its environment, naming the shell's root with the
103
120
  core beneath it in `node_modules/projectstore/`, and **no project-directory
104
121
  variable at all**. The project comes from the payload's `cwd`, which every
@@ -1,5 +1,5 @@
1
1
  {
2
- "_comment": "Harness capability manifest โ€” Codex. The committed adapters/codex tree renders the source commands, roles, passive skills and hooks into Codex vocabulary. Measurements began with 759 captured hook firings on 2026-09-07/08; the complete built shell, isolated marketplace install, upgrade, validator and fresh-session skill load passed on codex-cli 0.153.4 on 2026-09-30. The validator reads only .codex-plugin/plugin.json; the canonical root plugin.json has not been validated.",
2
+ "_comment": "Harness capability manifest โ€” Codex. The committed adapters/codex tree renders the source commands, roles, passive skills and hooks into Codex vocabulary. Measurements began with 759 captured hook firings on 2026-09-07/08; the complete built shell, isolated marketplace install, upgrade, validator and fresh-session skill load passed on codex-cli 0.153.4 on 2026-09-30. The validator reads only .codex-plugin/plugin.json, which from 0.28.2 is the shell's one manifest: Codex picks a root Agent Plugins plugin.json first and has loaded no hooks from that format since openai/codex#37027 (merged 2026-08-05).",
3
3
  "id": "codex",
4
4
  "display_name": "Codex",
5
5
  "emit": true,
@@ -7,7 +7,7 @@
7
7
  "output_dir": "adapters/codex",
8
8
  "docs": "https://developers.openai.com/codex/",
9
9
  "verified": null,
10
- "verified_reason": "Null, restored 2026-10-03. docs/harnesses.md calls a harness supported only when every installed surface has been exercised end to end, and contract 16 of the generation spec (Generated harness surfaces: manifests, the generator and the three invariants) derives that label from this field. The 2026-09-30 run (session 01a0f079-7ecd-7331-95a9-2471def3cb22) exercised one surface: a fresh `codex exec` session loaded projectstore-status from the materialised cache. The hooks were not exercised, and the first real install showed why that matters. Its cached hooks, run by hand through `zsh -lc` (a form the failure did not depend on: read from source, 0.153.4 runs a hook as `<session shell> -c` with the Codex process's environment, and `$SHELL -lc` only as a fallback), could not load the vault in any session; in the first, the failure sat beneath the welcome. The core had taken the shell's root for its own. That is fixed and pinned by a test that runs every rendered hook from the built shell. This block is set by a live run that exercises every installed surface: the hooks once registration has settled, including PreCompact, and the skill flows.",
10
+ "verified_reason": "Null, restored 2026-10-03. docs/harnesses.md calls a harness supported only when every installed surface has been exercised end to end, and contract 16 of the generation spec (Generated harness surfaces: manifests, the generator and the three invariants) derives that label from this field. The 2026-09-30 run (session 01a0f079-7ecd-7331-95a9-2471def3cb22) exercised one surface: a fresh `codex exec` session loaded projectstore-status from the materialised cache. The hooks were not exercised, and the first real install showed why that matters. Its cached hooks, run by hand through `zsh -lc` (a form the failure did not depend on: read from source, 0.153.4 runs a hook as `<session shell> -c` with the Codex process's environment, and `$SHELL -lc` only as a fallback), could not load the vault in any session; in the first, the failure sat beneath the welcome. The core had taken the shell's root for its own. That is fixed and pinned by a test that runs every rendered hook from the built shell. This block is set by a live run that exercises every installed surface: the hooks once registration has settled, including PreCompact, and the skill flows. The shell is published from 0.28.1, ahead of that run, by the maintainer's decision of 2026-10-04; publication does not set this block.",
11
11
  "runtime": {
12
12
  "detect_env": [
13
13
  "PLUGIN_ROOT",
@@ -54,7 +54,7 @@
54
54
  },
55
55
  "hooks": {
56
56
  "config_file": "hooks/hooks.json",
57
- "config_file_reason": "The canonical portable plugin.json selects ./hooks/hooks.json under extensions.com.openai; the compatibility manifest selects the same root-relative file. This keeps one rendered hook definition for both loaders. The legacy inline form fired 757 events across five event types; the file-selected portable form is gated by the compatibility matrix and fresh-session run.",
57
+ "config_file_reason": "Codex's default hooks file. A legacy .codex-plugin/plugin.json with no `hooks` key falls back to hooks/hooks.json (DEFAULT_HOOKS_CONFIG_FILE in codex-rs/core-plugins/src/loader.rs at rust-v0.160.0), so the manifest names no hooks at all. The shell ships no root Agent Plugins plugin.json. Codex picks that manifest first and then loads no hooks from it, a runtime boundary since openai/codex#37027 (loader.rs:955 at rust-v0.153.4, 952-962 at rust-v0.160.0). With one, the maintainer's codex-cli 0.160.0 listed none of ours in /hooks on 2026-10-04; with the file renamed away in the installed cache, it listed all six. The app-server's hooks/list agrees: 0 for 0.28.1's root, 6 for 0.28.2's. The spike's inline form fired 757 events across five event types.",
58
58
  "events": {
59
59
  "SessionStart": "SessionStart",
60
60
  "PreToolUse": "PreToolUse",
@@ -192,7 +192,7 @@
192
192
  "supported": true,
193
193
  "kind": "host",
194
194
  "scope": "user",
195
- "scope_reason": "Selected by canonical plugin.json and the compatibility manifest, then loaded with the plugin; trust is granted per hook, machine-wide, and cannot be silenced per checkout."
195
+ "scope_reason": "Loaded with the plugin from its default hooks/hooks.json, which .codex-plugin/plugin.json leaves to Codex by naming no hooks; trust is granted per hook, machine-wide, and cannot be silenced per checkout."
196
196
  },
197
197
  "mcp": {
198
198
  "supported": false,
@@ -290,7 +290,8 @@
290
290
  "rewrites": [],
291
291
  "install": {
292
292
  "mechanism": "the package's portable plugin root, registered through its distribution shell and Codex's own marketplace CLI",
293
- "shell_reason": "The built `projectstore-codex` shell carries the rendered Codex skills and hooks plus an exact bundled core, fixes --harness codex, stages a stable marketplace under CODEX_HOME, and asks Codex itself to install it. The `shell` key is deliberately absent until its first npm publication, so generated guidance cannot send users to the reserved placeholder package.",
293
+ "shell": "projectstore-codex",
294
+ "shell_reason": "The built `projectstore-codex` shell carries the rendered Codex skills and hooks plus an exact bundled core, fixes --harness codex, stages a stable marketplace under CODEX_HOME, and asks Codex itself to install it. It is published from 0.28.1, by the maintainer's decision of 2026-10-04. Until then this key was absent, so generated guidance could not send users to the reserved 0.0.1 placeholder; the core alone is not Codex's plugin root and cannot register it.",
294
295
  "why_not_scripted": "The shell does not edit Codex's registry or cache. It atomically stages the plugin source, previews the host commands, then runs `codex plugin marketplace add` and `codex plugin add`; a read-back verifies the installed version and payload digest. The global plugin survives ordinary project uninstall; `uninstall --global` is the explicit destructive form.",
295
296
  "steps": [
296
297
  "npx projectstore-codex install --project \"$PWD\"",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "projectstore",
3
- "version": "0.28.0",
3
+ "version": "0.28.2",
4
4
  "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.",
5
5
  "keywords": [
6
6
  "project-management",
@@ -271,14 +271,17 @@ function planAgentsBlock(ctx, key, s) {
271
271
  // One host command as a plan step: the verbatim argv (the manifest's
272
272
  // subcommand with its placeholders filled), why it runs, and the host-owned
273
273
  // files it is known to touch (measured 2026-09-05 โ€” the manifest's cli.verified).
274
+ // A portable registration keeps its marketplace and enablement stanzas in one
275
+ // global config (registry.global_config; Codex's config.toml, measured
276
+ // 2026-09-07), so the preview names that file wherever a step rewrites it.
274
277
  function hostStep(a, s, name, fill, why) {
275
278
  const template = s.cli.commands[name];
276
279
  if (!Array.isArray(template) || !template.length) throw new Error(`${s.format}: host operation ${name} is not declared`);
277
280
  const argv = template.map((t) => t.replace(/\{(\w+)\}/g, (_, k) => fill[k] ?? `{${k}}`));
278
281
  const p = a.paths;
279
282
  const touches = {
280
- validate: [], marketplace_add: [p.marketplaces, p.projectSettings], marketplace_update: [p.marketplaces], marketplace_remove: [p.marketplaces, p.projectSettings],
281
- install: [p.installed, p.projectSettings, p.cacheDir], update: [p.installed, p.cacheDir], uninstall: [p.installed, p.projectSettings], disable: [p.projectSettings], enable: [p.projectSettings],
283
+ validate: [], marketplace_add: [p.marketplaces, p.globalConfig, p.projectSettings], marketplace_update: [p.marketplaces], marketplace_remove: [p.marketplaces, p.globalConfig, p.projectSettings],
284
+ install: [p.installed, p.globalConfig, p.projectSettings, p.cacheDir], update: [p.installed, p.cacheDir], uninstall: [p.installed, p.globalConfig, p.projectSettings], disable: [p.projectSettings], enable: [p.projectSettings],
282
285
  }[name] || [];
283
286
  return { kind: "host", name, bin: s.cli.bin, argv, why, touches: touches.filter(Boolean) };
284
287
  }
@@ -68,10 +68,16 @@ export function collectShells(root = ROOT) {
68
68
  if (typeof json.version !== "string" || !json.version) return { error: `${rel}: no version found where one is required` };
69
69
  const pluginVersions = [];
70
70
  if (name === "projectstore-codex") {
71
- for (const manifest of ["plugin.json", ".codex-plugin/plugin.json"]) {
71
+ // A root plugin.json is an Agent Plugins manifest Codex picks first, and
72
+ // Codex loads no hooks from that format (openai/codex#37027, merged
73
+ // 2026-08-05): every hook goes missing.
74
+ if (existsSync(resolve(root, SHELLS_DIR, name, "plugin.json"))) {
75
+ return { error: `${SHELLS_DIR}/${name}/plugin.json: refused โ€” Codex picks a root Agent Plugins manifest first and loads no hooks from it (openai/codex#37027; codex-rs/core-plugins/src/loader.rs); the shell's manifest is .codex-plugin/plugin.json alone` };
76
+ }
77
+ for (const manifest of [".codex-plugin/plugin.json"]) {
72
78
  const manifestRel = `${SHELLS_DIR}/${name}/${manifest}`;
73
79
  const manifestAbs = resolve(root, manifestRel);
74
- if (!existsSync(manifestAbs)) return { error: `${manifestRel}: missing โ€” the Codex shell carries both canonical and compatibility manifests` };
80
+ if (!existsSync(manifestAbs)) return { error: `${manifestRel}: missing โ€” the Codex shell's one manifest` };
75
81
  let parsed;
76
82
  try { parsed = JSON.parse(readFileSync(manifestAbs, "utf8")); } catch (e) { return { error: `${manifestRel}: ${e.message}` }; }
77
83
  if (typeof parsed.version !== "string" || !parsed.version) return { error: `${manifestRel}: no version found where one is required` };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "projectstore-claude",
3
- "version": "0.28.0",
3
+ "version": "0.28.2",
4
4
  "description": "Installs projectstore for Claude Code from npm: the core pinned and bundled, the harness fixed โ€” npx projectstore-claude install --project \"$PWD\".",
5
5
  "keywords": [
6
6
  "projectstore",
@@ -37,7 +37,7 @@
37
37
  "README.md"
38
38
  ],
39
39
  "dependencies": {
40
- "projectstore": "=0.28.0"
40
+ "projectstore": "=0.28.2"
41
41
  },
42
42
  "bundleDependencies": [
43
43
  "projectstore"