From 9b6cf0d6bc0297fbb4251add6063e6fdc4dccf02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Almir=20Saraj=C4=8Di=C4=87?= Date: Wed, 2 Sep 2026 09:31:28 +0300 Subject: [PATCH] fix(hooks): stop injecting Basecamp into every session --- README.md | 2 +- hooks/hooks.json | 15 +-------------- install.md | 2 +- internal/commands/wizard_codex.go | 2 -- internal/commands/wizard_codex_test.go | 5 ++--- internal/release/manifests_test.go | 1 + 6 files changed, 6 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 29cb2643c..2e4b046e5 100644 --- a/README.md +++ b/README.md @@ -232,7 +232,7 @@ CLI needs upgrading. **Claude Code:** `basecamp setup claude` — installs the plugin with skills, hooks, and agent workflow support. -**Codex:** `basecamp setup codex` — registers the 37signals marketplace and installs the native plugin with Basecamp skills, diagnostics, and opt-in hooks. In Codex, review and trust the plugin hooks with `/hooks`, then start a new thread to load the skills and hooks. +**Codex:** `basecamp setup codex` — registers the 37signals marketplace and installs the native plugin with Basecamp skills, diagnostics, and opt-in commit-reference hooks. In Codex, review and trust the plugin hooks with `/hooks`, then start a new thread to load the skills and hooks. The plugin does not inject Basecamp context at session start; Codex selects the skill when a request is relevant or explicitly references Basecamp. Manual Codex installation uses the same marketplace: diff --git a/hooks/hooks.json b/hooks/hooks.json index 09bd2cfa3..91e64a90b 100644 --- a/hooks/hooks.json +++ b/hooks/hooks.json @@ -1,19 +1,6 @@ { - "description": "Basecamp agent hooks: session context and commit-reference nudges.", + "description": "Basecamp agent hooks: commit-reference nudges.", "hooks": { - "SessionStart": [ - { - "matcher": "startup|resume|clear|compact", - "hooks": [ - { - "type": "command", - "command": "basecamp agent-hook session-start", - "timeout": 5, - "statusMessage": "Checking Basecamp status" - } - ] - } - ], "PreToolUse": [ { "matcher": "Bash", diff --git a/install.md b/install.md index 6ab458d68..fb8ca1187 100644 --- a/install.md +++ b/install.md @@ -152,7 +152,7 @@ plugin, run `basecamp upgrade` and start a new session; `basecamp agent-hook basecamp setup codex ``` -This installs the shared Basecamp skill, registers the 37signals Codex marketplace, and installs the native plugin. After setup, review and trust the plugin hooks with `/hooks` (Codex lists untrusted hooks but does not run them until trusted), then start a new Codex thread to load the skills and hooks. +This installs the shared Basecamp skill, registers the 37signals Codex marketplace, and installs the native plugin. After setup, review and trust the plugin's commit-reference hooks with `/hooks` (Codex lists untrusted hooks but does not run them until trusted), then start a new Codex thread to load the skills and hooks. The plugin does not inject Basecamp context at session start; Codex selects the skill when a request is relevant or explicitly references Basecamp. For a manual install: diff --git a/internal/commands/wizard_codex.go b/internal/commands/wizard_codex.go index 314b7ad7f..33952dba3 100644 --- a/internal/commands/wizard_codex.go +++ b/internal/commands/wizard_codex.go @@ -65,8 +65,6 @@ func runCodexSetup(cmd *cobra.Command, styles *tui.Styles) error { fmt.Fprintln(w, styles.RenderStatus(true, "37signals marketplace ready")) fmt.Fprintln(w, styles.RenderStatus(true, "Codex plugin installed and enabled")) fmt.Fprintln(w) - // Trust must come first: an untrusted SessionStart hook is silently - // skipped, so a thread started before trusting gets no hook context. fmt.Fprintln(w, styles.Muted.Render(" Review and trust the plugin hooks with /hooks.")) fmt.Fprintln(w, styles.Muted.Render(" Then start a new Codex thread to load the Basecamp skills.")) return nil diff --git a/internal/commands/wizard_codex_test.go b/internal/commands/wizard_codex_test.go index b98f45fec..6c66dceab 100644 --- a/internal/commands/wizard_codex_test.go +++ b/internal/commands/wizard_codex_test.go @@ -156,9 +156,8 @@ func TestRunCodexSetupInteractiveExplainsNextSteps(t *testing.T) { assert.Contains(t, output.String(), "Registering 37signals marketplace") assert.Contains(t, output.String(), "Installing basecamp plugin") - // Codex lists untrusted hooks but does not run them until trusted, and - // an untrusted SessionStart is skipped — so the trust step must come - // before the new-thread step. + // Codex lists untrusted hooks but does not run them until trusted, so + // complete hook setup before starting the thread that loads the skills. trustAt := strings.Index(output.String(), "trust the plugin hooks with /hooks") newThreadAt := strings.Index(output.String(), "start a new Codex thread") require.GreaterOrEqual(t, trustAt, 0) diff --git a/internal/release/manifests_test.go b/internal/release/manifests_test.go index de52143c2..34d472acf 100644 --- a/internal/release/manifests_test.go +++ b/internal/release/manifests_test.go @@ -140,6 +140,7 @@ func TestHooksFileCommandsInvokeBasecamp(t *testing.T) { } require.NoError(t, json.Unmarshal(data, &config)) require.NotEmpty(t, config.Hooks) + assert.NotContains(t, config.Hooks, "SessionStart", "plugins must not inject Basecamp context into every agent session") for event, matchers := range config.Hooks { require.NotEmpty(t, matchers, event)