start-vibing-stacks 2.22.0 → 2.23.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 CHANGED
@@ -6,7 +6,7 @@ Multi-stack AI workflow for **Claude Code** & **Cursor**. One command installs a
6
6
  npx start-vibing-stacks
7
7
  ```
8
8
 
9
- > Latest: **v2.12.0** — `security-auditor` rewritten as stack-aware adversarial auditor with VETO power; `documenter` rewritten with search-optimized memory layer (YAML frontmatter + `_index.json` sidecar); `research-web` MCP-first; CI on Node 22.
9
+ > Latest: **v2.23.0** — multi-instance coordination layer. Two or more Claude Code sessions in the same folder auto-discover each other through `.claude/state/`, share file-edit awareness, and refuse to overwrite each other's uncommitted work. New `/peers` slash command + `peers list/notify/locks/cleanup` CLI.
10
10
 
11
11
  ---
12
12
 
@@ -16,8 +16,8 @@ npx start-vibing-stacks
16
16
  |---|---|---|
17
17
  | Agents | **7** universal | `research-web` (MCP-first) · `documenter` (memory layer) · `domain-updater` · `commit-manager` · `tester` · `claude-md-compactor` (compaction) · **`security-auditor` (VETO)** |
18
18
  | Skills | **22** shared + **7–14** stack-specific + **2–7** frontend | Versioned (`version:` frontmatter), upgradable via `migrate` |
19
- | Hooks | `stop-validator` · `final-check` · `user-prompt-submit` | Block completion on git/docs/secrets/code-quality issues |
20
- | Commands | `/feature` · `/fix` · `/research` · `/validate` | Slash commands |
19
+ | Hooks | `session-start` · `user-prompt-submit` · `pre-tool-use` · `post-tool-use` · `stop-validator` · `final-check` | Multi-instance coordination + git/docs/secrets/code-quality gates |
20
+ | Commands | `/feature` · `/fix` · `/research` · `/validate` · `/peers` | Slash commands |
21
21
  | Workflows | `ci.yml` + `security.yml` per stack | Copied to `.github/workflows/` when target is empty |
22
22
  | Configs | `active-project.json` · `domain-mapping.json` · `security-rules.json` · `standards-review.json` | Drives every agent's stack detection |
23
23
 
@@ -82,14 +82,51 @@ your-project/
82
82
  │ │ │ ├── _index.json # machine-readable, regenerated by documenter
83
83
  │ │ │ └── domains/ # one file per domain (≤ 8 KB each)
84
84
  │ │ └── <other skills>/
85
- │ ├── hooks/ # stop-validator, final-check, prompt-submit
86
- │ ├── commands/ # /feature, /fix, /research, /validate
85
+ │ ├── hooks/ # session-start, pre/post-tool-use, stop-validator, final-check, prompt-submit, peers (CLI)
86
+ │ ├── commands/ # /feature, /fix, /research, /validate, /peers
87
+ │ ├── state/ # multi-instance coordination (gitignored, runtime-managed)
87
88
  │ └── config/ # active-project, domain-mapping, security-rules, ...
88
89
  └── .github/workflows/ # ci.yml + security.yml (if dir was empty)
89
90
  ```
90
91
 
91
92
  ---
92
93
 
94
+ ## Multiple Claude instances in the same folder
95
+
96
+ When two or more Claude Code sessions run in the same project, the installed hooks coordinate automatically through `.claude/state/` (gitignored, per-host).
97
+
98
+ What you get:
99
+
100
+ - **Auto-discovery** — `SessionStart` registers each session, captures the same title that appears in `claude --resume`, and tells you who else is around.
101
+ - **File-edit collision shield** — `PreToolUse` BLOCKS Edit/Write on a file a peer is actively editing (heartbeat <60s, touched <5min ago). Idle peers (60s–30min) downgrade to a warning; stale peers are ignored.
102
+ - **Cross-instance messaging** — `peers notify <id-prefix> "msg"` queues a message that surfaces in the OTHER instance at its next prompt. The user-prompt-submit hook drains the inbox automatically.
103
+
104
+ ### `/peers` CLI
105
+
106
+ ```bash
107
+ # Inside Claude:
108
+ /peers # delegates to the script
109
+
110
+ # Or from any terminal:
111
+ npx tsx .claude/hooks/peers.ts list
112
+ npx tsx .claude/hooks/peers.ts notify a1b2c3d4 "I just committed auth changes"
113
+ npx tsx .claude/hooks/peers.ts locks --minutes 10
114
+ npx tsx .claude/hooks/peers.ts cleanup
115
+ ```
116
+
117
+ ### Heartbeat thresholds
118
+
119
+ | Last activity | State | Effect |
120
+ | ------------- | -------- | -------------------------------------------------------- |
121
+ | < 60s | active | Counts for collision detection; BLOCKS conflicting edits |
122
+ | 60s – 30min | idle | Surfaced as a warning; edits NOT blocked |
123
+ | > 30min | stale | Auto-archived |
124
+ | > 24h | removed | Deleted |
125
+
126
+ Single-host coordination only. It does **not** replace `git` for cross-machine collaboration; it prevents two live sessions on the same laptop from stepping on the same uncommitted file.
127
+
128
+ ---
129
+
93
130
  ## CLI
94
131
 
95
132
  ```bash
package/dist/setup.js CHANGED
@@ -68,6 +68,10 @@ export async function setupProject(projectDir, config, options = {}) {
68
68
  mkdirSync(join(claudeDir, 'commands'), { recursive: true });
69
69
  mkdirSync(join(claudeDir, 'rules'), { recursive: true });
70
70
  mkdirSync(join(claudeDir, 'skills', 'codebase-knowledge', 'domains'), { recursive: true });
71
+ // Multi-instance coordination state (gitignored, runtime-managed)
72
+ mkdirSync(join(claudeDir, 'state', 'sessions', '_archive'), { recursive: true });
73
+ mkdirSync(join(claudeDir, 'state', 'inbox'), { recursive: true });
74
+ mkdirSync(join(claudeDir, 'state', 'file-touches', '_archive'), { recursive: true });
71
75
  spinner.text = 'Directory structure created';
72
76
  // 2. Copy shared agents (universal)
73
77
  const sharedAgentsDir = join(PACKAGE_ROOT, 'stacks', '_shared', 'agents');
@@ -79,6 +83,12 @@ export async function setupProject(projectDir, config, options = {}) {
79
83
  // 4. Copy shared hooks
80
84
  const sharedHooksDir = join(PACKAGE_ROOT, 'stacks', '_shared', 'hooks');
81
85
  const hookCount = copyDirRecursive(sharedHooksDir, join(claudeDir, 'hooks'), options.force);
86
+ // 4b. Multi-instance coordination README in state dir
87
+ const stateReadmeSrc = join(PACKAGE_ROOT, 'stacks', '_shared', 'hooks', '_state.README.md');
88
+ const stateReadmeDest = join(claudeDir, 'state', 'README.md');
89
+ if (existsSync(stateReadmeSrc) && (!existsSync(stateReadmeDest) || options.force)) {
90
+ writeFileSync(stateReadmeDest, readFileSync(stateReadmeSrc, 'utf8'));
91
+ }
82
92
  // 5. Copy shared config
83
93
  const sharedConfigDir = join(PACKAGE_ROOT, 'stacks', '_shared', 'config');
84
94
  copyDirRecursive(sharedConfigDir, join(claudeDir, 'config'), options.force);
@@ -140,13 +150,21 @@ export async function setupProject(projectDir, config, options = {}) {
140
150
  spinner.text = 'Imported .cursorrules into Claude config';
141
151
  }
142
152
  }
143
- // 11b. Ensure CLAUDE.local.md is gitignored
153
+ // 11b. Ensure CLAUDE.local.md and .claude/state/ are gitignored
144
154
  const gitignorePath = join(projectDir, '.gitignore');
145
155
  if (existsSync(gitignorePath)) {
146
- const gitignore = readFileSync(gitignorePath, 'utf8');
156
+ let gitignore = readFileSync(gitignorePath, 'utf8');
157
+ let changed = false;
147
158
  if (!gitignore.includes('CLAUDE.local.md')) {
148
- writeFileSync(gitignorePath, gitignore.trimEnd() + '\n\n# Claude Code local preferences\nCLAUDE.local.md\n');
159
+ gitignore = gitignore.trimEnd() + '\n\n# Claude Code local preferences\nCLAUDE.local.md\n';
160
+ changed = true;
161
+ }
162
+ if (!gitignore.match(/^\.claude\/state\/?$/m) && !gitignore.match(/^\.claude\/?$/m)) {
163
+ gitignore = gitignore.trimEnd() + '\n\n# Claude Code multi-instance coordination state (runtime, per-host)\n.claude/state/\n';
164
+ changed = true;
149
165
  }
166
+ if (changed)
167
+ writeFileSync(gitignorePath, gitignore);
150
168
  }
151
169
  // 11c. Save standards review results
152
170
  if (config.standardsReview) {
@@ -230,6 +248,17 @@ export async function setupProject(projectDir, config, options = {}) {
230
248
  deny: [],
231
249
  },
232
250
  hooks: {
251
+ SessionStart: [
252
+ {
253
+ hooks: [
254
+ {
255
+ type: 'command',
256
+ command: 'npx tsx "$CLAUDE_PROJECT_DIR/.claude/hooks/session-start.ts"',
257
+ timeout: 10,
258
+ },
259
+ ],
260
+ },
261
+ ],
233
262
  UserPromptSubmit: [
234
263
  {
235
264
  matcher: '',
@@ -242,6 +271,30 @@ export async function setupProject(projectDir, config, options = {}) {
242
271
  ],
243
272
  },
244
273
  ],
274
+ PreToolUse: [
275
+ {
276
+ matcher: 'Edit|Write|MultiEdit|NotebookEdit',
277
+ hooks: [
278
+ {
279
+ type: 'command',
280
+ command: 'npx tsx "$CLAUDE_PROJECT_DIR/.claude/hooks/pre-tool-use.ts"',
281
+ timeout: 5,
282
+ },
283
+ ],
284
+ },
285
+ ],
286
+ PostToolUse: [
287
+ {
288
+ matcher: 'Edit|Write|MultiEdit|NotebookEdit',
289
+ hooks: [
290
+ {
291
+ type: 'command',
292
+ command: 'npx tsx "$CLAUDE_PROJECT_DIR/.claude/hooks/post-tool-use.ts"',
293
+ timeout: 5,
294
+ },
295
+ ],
296
+ },
297
+ ],
245
298
  Stop: [
246
299
  {
247
300
  hooks: [
@@ -253,6 +306,17 @@ export async function setupProject(projectDir, config, options = {}) {
253
306
  ],
254
307
  },
255
308
  ],
309
+ SessionEnd: [
310
+ {
311
+ hooks: [
312
+ {
313
+ type: 'command',
314
+ command: 'npx tsx "$CLAUDE_PROJECT_DIR/.claude/hooks/stop-validator.ts"',
315
+ timeout: 10,
316
+ },
317
+ ],
318
+ },
319
+ ],
256
320
  },
257
321
  agents: {
258
322
  'research-web': {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "start-vibing-stacks",
3
- "version": "2.22.0",
3
+ "version": "2.23.0",
4
4
  "description": "AI-powered multi-stack dev workflow for Claude Code. Supports PHP, Node.js, Python and more.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,37 @@
1
+ ---
2
+ name: peers
3
+ description: Inspect or talk to other Claude Code instances running in this same project (multi-instance coordination layer).
4
+ version: 1.0.0
5
+ ---
6
+
7
+ # /peers — Multi-Instance Coordination
8
+
9
+ Use this when the user asks something like:
10
+
11
+ - "is there another Claude running in this folder?"
12
+ - "tell the other instance I finished the auth work"
13
+ - "who touched `src/x.ts` recently?"
14
+ - "clean up dead sessions"
15
+
16
+ Run the `peers` CLI via Bash. The script lives at `.claude/hooks/peers.ts` and is installed by `start-vibing-stacks`.
17
+
18
+ ## Usage
19
+
20
+ | Goal | Command |
21
+ |---|---|
22
+ | List active + idle peer sessions | `npx tsx "$CLAUDE_PROJECT_DIR/.claude/hooks/peers.ts" list` |
23
+ | Notify another instance | `npx tsx "$CLAUDE_PROJECT_DIR/.claude/hooks/peers.ts" notify <id-prefix> "message"` |
24
+ | See who touched what file recently | `npx tsx "$CLAUDE_PROJECT_DIR/.claude/hooks/peers.ts" locks --minutes 10` |
25
+ | Remove stale sessions | `npx tsx "$CLAUDE_PROJECT_DIR/.claude/hooks/peers.ts" cleanup` |
26
+
27
+ The `<id-prefix>` is the 8-character short id printed by `peers list`, or any substring of the peer's title.
28
+
29
+ ## Output rules
30
+
31
+ - Always quote the short id (first 8 chars), the title, and the idle time when reporting peers to the user.
32
+ - If `peers notify` succeeds, tell the user the message will surface in the OTHER instance at the start of its next prompt (drained by `user-prompt-submit.ts`).
33
+ - If `peers list` says "No peer sessions", confirm that to the user and DO NOT suggest workarounds.
34
+
35
+ ## Background
36
+
37
+ State lives in `.claude/state/` (gitignored). Hooks `session-start.ts`, `user-prompt-submit.ts`, `pre-tool-use.ts`, `post-tool-use.ts` and `stop-validator.ts` keep it in sync. See `multi-instance-coordination` skill for the full protocol.
@@ -0,0 +1,55 @@
1
+ # `.claude/state/` — Multi-Instance Coordination
2
+
3
+ > This directory is **gitignored** and managed automatically by hooks. Safe to delete; it will be recreated by the next Claude session.
4
+
5
+ When two or more Claude Code instances run in the same project folder, the hooks under `.claude/hooks/` use this directory to:
6
+
7
+ 1. announce themselves to each other (`sessions/<id>.json`)
8
+ 2. record file edits as they happen (`file-touches.jsonl`)
9
+ 3. prevent simultaneous writes to the same file (PreToolUse hook reads the touch log)
10
+ 4. exchange messages (`inbox/<id>.jsonl` — drained at next prompt)
11
+
12
+ ## Layout
13
+
14
+ ```
15
+ .claude/state/
16
+ sessions/
17
+ <session-id>.json one record per active instance (heartbeat-tracked)
18
+ _archive/ sessions ended or stale (>30min idle)
19
+ inbox/
20
+ <session-id>.jsonl queued messages for that session
21
+ file-touches.jsonl append-only Edit/Write log (rotates every 1000 lines)
22
+ file-touches/_archive/ rotated logs
23
+ ```
24
+
25
+ ## Heartbeat thresholds
26
+
27
+ | Last activity | State | Effect |
28
+ | ------------- | -------- | --------------------------------------------------------------------------- |
29
+ | < 60s | active | Counts for collision detection. PreToolUse may **block** Edit/Write. |
30
+ | 60s – 30min | idle | Surfaced as a warning in `systemMessage`. Edits are **not** blocked. |
31
+ | > 30min | stale | Auto-archived on the next sweep. |
32
+ | > 24h | removed | Deleted entirely. |
33
+
34
+ ## Viewing peers
35
+
36
+ From inside Claude or a terminal:
37
+
38
+ ```
39
+ /peers
40
+ ```
41
+
42
+ or directly:
43
+
44
+ ```
45
+ npx tsx .claude/hooks/peers.ts list
46
+ npx tsx .claude/hooks/peers.ts notify <id-prefix> "message"
47
+ npx tsx .claude/hooks/peers.ts locks --minutes 10
48
+ npx tsx .claude/hooks/peers.ts cleanup
49
+ ```
50
+
51
+ ## Safety
52
+
53
+ - All state writes are atomic (`.tmp` + `rename`).
54
+ - All reads are tolerant of corruption — hooks never block Claude on a malformed file.
55
+ - This is a single-host coordination layer. It does **not** replace git; it only prevents two live sessions from stepping on the same uncommitted edit.