convene-cli 1.0.2 → 1.0.3

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.
@@ -296,8 +296,28 @@ async function init(opts) {
296
296
  else {
297
297
  log('· CONVENE_PROTOCOL.md (exists — left as-is)');
298
298
  }
299
- // 7. hook
299
+ // 7. hook (global, per-machine — fires in every repo, no-op outside convene repos)
300
300
  registerHook(skipHook);
301
+ // 7a. committed project hook — the repo CARRIES the same `convene fetch` hook in
302
+ // .claude/settings.json, so a teammate who opens it auto-connects (Claude Code
303
+ // applies project hooks after a one-time trust prompt; identical command de-dups
304
+ // against the global hook, so no double-fire).
305
+ if (skipHook) {
306
+ log('Skipped committed project hook (--no-hook).');
307
+ }
308
+ else {
309
+ const r = (0, hook_1.ensureProjectHookRegistered)(top);
310
+ if (r === 'manual') {
311
+ log('· .claude/settings.json left as-is (existing settings unparseable).');
312
+ }
313
+ else {
314
+ log(`${r === 'registered' ? '✓' : '·'} .claude/settings.json (committed \`convene fetch\` hook — teammates auto-connect on open)`);
315
+ if ((0, git_1.gitPathIsIgnored)(top, node_path_1.default.join('.claude', 'settings.json'))) {
316
+ log(' ⚠ .claude/settings.json is git-ignored — commit it (or drop the .claude ignore) so teammates inherit the hook;');
317
+ log(' otherwise they connect via `convene setup`.');
318
+ }
319
+ }
320
+ }
301
321
  // 7b. committed git pre-push hook — the tool-agnostic backstop that auto-posts a
302
322
  // [STATUS] when work is pushed (fires for Codex/Cowork/humans, not just Claude).
303
323
  installGitHookStep(top, skipGithook);
@@ -62,6 +62,13 @@ async function join(opts) {
62
62
  : hook === 'already'
63
63
  ? 'Hook already registered.'
64
64
  : 'Could not auto-register the hook — run `convene doctor --fix` or add it manually.');
65
+ // Ensure the repo carries the committed `convene fetch` hook (.claude/settings.json)
66
+ // so the next teammate auto-connects on open. Idempotent; de-dups with the global hook.
67
+ if (top) {
68
+ const pr = (0, hook_1.ensureProjectHookRegistered)(top);
69
+ if (pr === 'registered')
70
+ log('Wrote committed project hook (.claude/settings.json) — commit it so teammates auto-connect.');
71
+ }
65
72
  // The tool-agnostic backstop: auto-post a [STATUS] when you push (works even
66
73
  // for tools without a per-prompt hook).
67
74
  if (top) {
package/dist/hook.js CHANGED
@@ -10,6 +10,8 @@ exports.hookIsRegistered = hookIsRegistered;
10
10
  exports.withHook = withHook;
11
11
  exports.serializeSettings = serializeSettings;
12
12
  exports.ensureHookRegistered = ensureHookRegistered;
13
+ exports.projectSettingsPath = projectSettingsPath;
14
+ exports.ensureProjectHookRegistered = ensureProjectHookRegistered;
13
15
  /**
14
16
  * Claude Code UserPromptSubmit hook registration in ~/.claude/settings.json.
15
17
  *
@@ -81,3 +83,33 @@ function ensureHookRegistered() {
81
83
  return 'manual';
82
84
  }
83
85
  }
86
+ /** The repo's COMMITTED, shared project settings file (vs settings.local.json, which is personal/gitignored). */
87
+ function projectSettingsPath(toplevel) {
88
+ return node_path_1.default.join(toplevel, '.claude', 'settings.json');
89
+ }
90
+ /**
91
+ * Ensure the SAME `convene fetch` hook in the repo's committed `.claude/settings.json`,
92
+ * so a teammate who opens the repo gets it automatically (Claude Code applies
93
+ * project hooks after a one-time per-repo trust prompt). Identical to the global
94
+ * hook command, so Claude Code de-dups them — no double-fire if both are present.
95
+ * Idempotent + merge-safe: never clobbers other project settings.
96
+ */
97
+ function ensureProjectHookRegistered(toplevel) {
98
+ const p = projectSettingsPath(toplevel);
99
+ const raw = readSettingsRaw(p);
100
+ const settings = parseSettings(raw);
101
+ if (settings === null)
102
+ return 'manual'; // unparseable — don't clobber
103
+ if (hookIsRegistered(settings))
104
+ return 'already';
105
+ try {
106
+ node_fs_1.default.mkdirSync(node_path_1.default.dirname(p), { recursive: true });
107
+ if (raw !== null)
108
+ node_fs_1.default.writeFileSync(p + '.bak', raw);
109
+ node_fs_1.default.writeFileSync(p, serializeSettings(withHook(settings)));
110
+ return 'registered';
111
+ }
112
+ catch {
113
+ return 'manual';
114
+ }
115
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "convene-cli",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Convene CLI — AI development coordination bus client + UserPromptSubmit hook. Install: npm i -g convene-cli; then `convene setup`.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://dev.convene.live",