Skip to content

Rename the agent plugin basecamp → basecamp-cli - #840

Merged
jeremy merged 13 commits into
mainfrom
rename-plugin-basecamp-cli
Oct 7, 2026
Merged

jeremy merged 13 commits into
mainfrom
rename-plugin-basecamp-cli

Conversation

@jeremy

@jeremy jeremy commented Oct 5, 2026 •

Copy link
Copy Markdown
Member

This PR renames the CLI's Claude Code and Codex plugin to basecamp-cli@37signals, so the basecamp name is free for the hosted Basecamp connector plugin. The basecamp binary and the skill names are unchanged. Existing installs keep working.

Deprecation window (with basecamp/claude-plugins#8)

  • Alias. The 37signals marketplace keeps basecamp as a deprecated alias of basecamp-cli, with the same source. Existing basecamp@37signals installs keep loading and updating.
  • Length: 7 days from the release that ships this (decided 2026-10-05). Removing the alias is its own later claude-plugins PR, and a later CLI release drops the stale handling. Retire the basecamp@37signals alias after the 7-day rename window #857 tracks both.
  • Re-pointing basecamp at the hosted connector comes after that. It also needs a CLI release that stops treating basecamp@37signals as stale. Until then, setup would uninstall the connector. AGENTS.md and the ClaudeLegacyPluginKey comment record this.

Merge and release order

Merge this together with basecamp/claude-plugins#8, #8 first:

  1. Merge claude-plugins#8. It adds the basecamp-cli entry and keeps basecamp as an alias with the same source. Both serve the current plugin. That marketplace has no tags or releases; main is what clients fetch.
  2. Merge this PR right after. The marketplace's unpinned url source serves main as soon as it lands. Installed copies don't move until the plugin version changes.
  3. Cut the release with scripts/release.sh. Its release-prep commit bumps .claude-plugin/plugin.json and .codex-plugin/plugin.json, then it tags v* and release.yml publishes. The bump delivers the renamed manifest and the notice to basecamp@37signals installs. The 7-day window starts here. This build installs basecamp-cli@37signals, which is why Add built-in OAuth credentials for production Launchpad #8 has to merge first.
  4. Only then submit the hosted plugin (plugins/basecamp in claude-plugins) to Anthropic's directory, which publishes it as basecamp. Before this release, CLI plugin installs still carry the manifest name basecamp, and the two would collide.
  5. After 7 days, per Retire the basecamp@37signals alias after the 7-day rename window #857: remove the alias from claude-plugins, then ship a CLI release without the basecamp@37signals stale handling.

What changes

  • Manifests. .claude-plugin/plugin.json and .codex-plugin/plugin.json use name: basecamp-cli. Setup installs basecamp-cli@37signals, and doctor checks for it.
  • Migration by key. During the window, basecamp@37signals only ever means this plugin.
    • Claude: setup treats it as a stale entry, like basecamp@basecamp. It uninstalls it per scope and reinstalls basecamp-cli at those scopes.
    • Codex: setup adds basecamp-cli first, then removes the old ID.
    • Doctor: reports the old name, and warns when both copies are installed.
  • One-time notice for alias users who never run setup. A SessionStart hook detects an install under the old ID from its plugin root (.../37signals/basecamp/<version>, via CLAUDE_PLUGIN_ROOT or Codex's PLUGIN_ROOT). It can't use the manifest, because the alias and basecamp-cli install identical files. Once per plugin data dir, it emits a systemMessage and context saying "The Basecamp plugin is now basecamp-cli … Run basecamp setup claude|codex to switch." Every other install stays silent.
  • The hook runs basecamp agent-hook pre-commit-snapshot, not a new subcommand. Every CLI that supports hooks already has that subcommand, and older versions ignore a SessionStart payload. A new subcommand made an older CLI fail every session start with unknown command; I observed this with 0.11.0. The release test allows that one SessionStart hook and nothing else, so the "no context injection" rule still holds.

End-to-end test (throwaway Claude config: HOME/CLAUDE_CONFIG_DIR in a temp dir, Claude Code 2.1.290)

  1. Installed basecamp@37signals from claude-plugins main (9dd90cb): 0.11.0, enabled.
  2. Pointed a local marketplace copy at this branch. It has basecamp-cli plus a basecamp alias with the same url source (a local clone with the version bumped to simulate a release). Ran marketplace update and plugin update basecamp@37signals: updated 0.11.0 → 0.12.x, still basecamp@37signals, still enabled. plugin details lists the skills and 4 hooks. So an install under the old ID loads the renamed manifest without trouble.
  3. Headless sessions (claude -p --include-hook-events):
    • CLI 0.11.0: SessionStart hook exit 0, no output.
    • This build: first session prints the notice (exit 0), second session prints nothing.
  4. basecamp doctor reported "Installed under the old name basecamp@37signals". basecamp setup claude left only basecamp-cli@37signals (user scope, 0.12.x). After that, doctor passes and the hook stays silent.

claude plugin validate passes on the plugin manifest. On the alias marketplace it passes with the existing "no marketplace description" warning.

Effect on users

  • Plugin skills are namespaced by plugin name, so basecamp:basecamp becomes basecamp-cli:basecamp after switching. The ~/.claude/skills/basecamp link is unchanged.
  • Codex treats hooks as untrusted until the user reviews them in /hooks. The new SessionStart hook won't run there until trusted, but Codex setup and doctor still migrate.

Testing

  • Unit tests cover:
    • the stale legacy key and the doctor messages;
    • Claude setup migrating at the same scopes;
    • Codex setup adding before removing, keeping the old ID while basecamp-cli is installed but disabled, and its removal-failure remediation;
    • the notice firing once for Claude and Codex roots, staying silent otherwise, and a SessionStart payload taking no snapshot;
    • the release-test hook rule.
  • e2e, skill-drift and surface checks pass locally.

Copilot AI balanced review requested due to automatic review settings October 5, 2026 22:15
@github-actions github-actions Bot added commands CLI command implementations tests Tests (unit and e2e) plugin Claude Code plugin docs labels Oct 5, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 15 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread internal/harness/claude.go Outdated
Comment thread internal/commands/wizard_codex_test.go Outdated
Comment thread internal/harness/codex.go
Comment thread README.md Outdated
Comment thread internal/harness/claude.go Outdated
Comment thread internal/harness/claude.go Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The manual migration commands can remove the hosted connector and use unsafe Codex ordering.

Review effort: Balanced
Findings: 1 Low severity

Open (1)
What changed in this PR

Renames the Claude and Codex plugin to basecamp-cli@37signals and migrates legacy installs safely.

Changes:

  • Updates manifests, setup commands, diagnostics, and documentation.
  • Detects legacy CLI plugins through repository manifests.
  • Adds migration and release-validation tests.

[!TIP]
If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.

File Description
README.md Documents renamed plugin and migration.
install.md Updates installation guidance.
AGENTS.md Records integration naming and migration rules.
.claude-plugin/​plugin.json Renames the Claude plugin.
.codex-plugin/​plugin.json Renames the Codex plugin.
internal/​harness/​claude.go Detects and classifies legacy Claude installs.
internal/​harness/​claude_test.go Tests Claude detection and migration cases.
internal/​harness/​codex.go Detects legacy cached Codex installs.
internal/​harness/​codex_test.go Tests Codex legacy detection and diagnostics.
internal/​commands/​wizard_agents.go Updates Claude setup labels and installation behavior.
internal/​commands/​wizard_test.go Tests Claude migration and command ordering.
internal/​commands/​wizard_codex.go Installs the replacement before legacy removal.
internal/​commands/​wizard_codex_test.go Tests Codex migration and failures.
internal/​commands/​setup_agents_test.go Updates expected manual commands.
internal/​release/​manifests_test.go Validates manifest names and repositories.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread README.md Outdated
Copilot AI balanced review requested due to automatic review settings October 5, 2026 22:30

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The documented unscoped Claude uninstall can remove a hosted connector installed at another scope.

Review effort: Balanced
Findings: 1 High severity

Open (1)
Resolved since last review (1)

Comment thread README.md Outdated
Copilot AI balanced review requested due to automatic review settings October 5, 2026 22:39

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Claude migration loses project-path identity, and Codex can remove the legacy plugin before verifying its replacement.

Review effort: Balanced
Findings: 1 High severity

Open (1)
Resolved since last review (1)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Verify replacement plugin before removing legacy entry

internal/​commands/​wizard_codex.go:122

This gate proves only that the legacy copy exists, not that the replacement is installed and enabled. The later verification already accounts for plugin add returning success without producing the expected installed state; if that happens while the legacy entry is still listed, this code removes the working legacy copy and only then reports verification failure, leaving neither usable. Verify the new plugin before removal, remove the legacy key only when the replacement is healthy, and retain the final post-removal check.

Comment thread internal/harness/claude.go Outdated
Copilot AI balanced review requested due to automatic review settings October 5, 2026 22:49

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The Codex failure remediation can remove the hosted connector without revalidating the ambiguous legacy key.

Review effort: Balanced
Findings: 1 High severity

Open (1)
Resolved since last review (1)

Comment thread internal/commands/wizard_codex.go

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Codex migration can remove a working legacy plugin before confirming that its replacement is installed and enabled.

Review effort: Balanced
Findings: None

Resolved since last review (1)
Previously missed (2)

In code that hasn't changed since last review

Medium severity Verify replacement plugin before removing legacy copy

internal/​commands/​wizard_codex.go:118

Verify that the replacement is installed and enabled before deleting the legacy copy. plugin add errors containing “already installed” are accepted above, so an existing but disabled basecamp-cli can reach this branch; CodexLegacyCLIInstalled only reports the old manifest and will remove the still-working legacy plugin, after which the final verification fails. Gate removal on CheckCodexPluginContext returning pass or warn first, then retain the final post-removal check.

Low severity Fix cross-reference to legacyCLIPluginEntries

internal/​harness/​claude.go:58

This cross-reference names legacyCLIInstall, which does not exist; the detection helper introduced below is legacyCLIPluginEntries. Pointing to the actual symbol keeps the safety rationale traceable.

Copilot AI balanced review requested due to automatic review settings October 5, 2026 23:02
@jeremy

jeremy commented Oct 5, 2026

Copy link
Copy Markdown
Member Author

Redesign (d3cc1e5). The review rounds on this PR all came back to one problem: telling the pre-rename CLI plugin apart from the hosted connector when both use basecamp@37signals. The fixes for it were the manifest/repository check, scope fail-closed, projectPath matching, CODEX_HOME cache reads, and keeping Codex remediation behind setup. Each round added another one. Instead of patching further, this removes the ambiguity: during the rename, the 37signals marketplace (basecamp/claude-plugins#8) lists basecamp-cli and no basecamp plugin, so basecamp@37signals can only be this CLI's old plugin and setup replaces it by key. The heuristics are deleted (net −290 lines).

Each case the heuristics handled, and where it lands now:

  • User scope: the existing stale path runs uninstall --scope user and reinstalls basecamp-cli at user scope.
  • Project/local scope (the projectPath thread): the scoped uninstall runs from the current directory. If that directory's entry is the old plugin, it is removed and reinstalled there. If the entry belongs to another checkout, the uninstall fails harmlessly and nothing is reinstalled. No hosted connector can be under this key, so neither outcome is destructive. Running setup in that checkout migrates it.
  • Missing or invalid scope (cubic P1): the unscoped fallback can only remove old-plugin installs now, so it is safe again.
  • v1 / array formats (the declined cubic thread): stalePluginKeys already parses these, so they are now migrated by key too.
  • Codex: legacy detection comes from codex plugin list alone. Setup adds basecamp-cli before removing the old plugin. The failure remediation is codex plugin remove basecamp@37signals again, which is safe now.
  • CODEX_HOME: it only mattered for reading cached manifests, which are no longer read.
  • Disabled install beside the old one: doctor still mentions the old copy.
  • Doctor: shows the old name when only the old plugin is installed. Claude and Codex warn when both copies are installed.
  • Manual README steps (the Copilot threads): uninstalling or removing by key is safe again. The README now installs first and then removes.

Follow-up constraint: re-adding basecamp to our marketplace for the hosted plugin is a later step. It waits for a deprecation window and for a CLI release that drops the basecamp@37signals stale handling. AGENTS.md and the ClaudeLegacyPluginKey comment record this.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Legacy detection relies on an ambiguous plugin key and can remove the hosted connector after the marketplace transition.

Review effort: Balanced
Findings: 2 High severity · 1 Medium severity

Open (3)

Comment thread internal/harness/claude.go
Comment thread internal/harness/codex.go
Comment thread internal/release/manifests_test.go

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 11 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread internal/commands/wizard_test.go Outdated
Comment thread internal/harness/claude.go
Comment thread internal/release/manifests_test.go
Copilot AI balanced review requested due to automatic review settings October 5, 2026 23:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Safe rollout depends on a coordinated marketplace change and a temporary external naming invariant requiring human verification.

Review effort: Balanced
Findings: None

Resolved since last review (3)

Copilot AI balanced review requested due to automatic review settings October 5, 2026 23:53
@jeremy
jeremy marked this pull request as ready for review October 6, 2026 00:29
@jeremy
jeremy requested a review from a team as a code owner October 6, 2026 00:29
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-07T01:29:55.394909Z 917e451 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

jeremy added 12 commits October 5, 2026 17:30
The 37signals marketplace gives the basecamp name to the hosted Basecamp
connector plugin, so this CLI's Claude Code and Codex plugin becomes
basecamp-cli@37signals. The CLI binary and skill names are unchanged.

setup claude and setup codex migrate a pre-rename install: an entry under
basecamp@37signals whose installed manifest names this repository is
replaced with basecamp-cli@37signals (Claude at the same scopes; Codex
removes the old copy only after the new one installs). An entry whose
manifest names anything else, or can't be read, is the hosted connector or
unknown, and is left alone. doctor reports the old name instead of
'Plugin not installed'.
… leftover copies

A legacy basecamp@37signals entry counts only at a scope claude plugin
uninstall --scope accepts, so setup can't fall back to an unscoped
uninstall of the shared key that would also remove a hosted connector.
doctor warns when the old copy is still installed next to basecamp-cli
(Claude), or alongside a disabled one (Codex). The README's manual steps
install first and remove the old key only after checking its manifest.
…elongs to

Claude resolves project and local scopes against the working directory, so
an uninstall run from another checkout would reach that checkout's entry
under the shared key, which may be the hosted connector. Such entries now
count as legacy only when their projectPath is the current directory.
…by manifest

The 37signals marketplace now lists no basecamp plugin during the rename, so
basecamp@37signals can only be this CLI's pre-rename plugin. Setup removes
it by key through the existing stale-entry path, and doctor reports it,
without the manifest, scope and projectPath checks that existed only to
tell it apart from a hosted connector under the same key. Re-adding
basecamp to the marketplace has to wait until this handling is dropped.
…i, once

During the deprecation window the marketplace keeps basecamp as an alias of
basecamp-cli with the same source, so existing installs keep working. A
SessionStart hook, agent-hook plugin-notice, recognizes an install under the
old id by its plugin root (.../37signals/basecamp/<version>), since the
manifest is the same for both, and says once that the plugin is now
basecamp-cli and which setup command switches it. Any other install stays
silent.
…tay silent

A new agent-hook subcommand fails with unknown command, on every session
start, for anyone whose CLI is older than the plugin. pre-commit-snapshot
exists in every hook-capable CLI and ignores a payload with no tool call,
so the SessionStart hook runs it and only CLIs that know the notice act on
the SessionStart event.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 795b275796

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/harness/claude.go
Comment thread internal/harness/claude.go
Copilot AI balanced review requested due to automatic review settings October 6, 2026 00:34
@jeremy
jeremy force-pushed the rename-plugin-basecamp-cli branch from 795b275 to dcd43bb Compare October 6, 2026 00:34

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dcd43bbe28

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/commands/wizard_codex.go
Comment thread internal/harness/claude.go
Codex keeps a disabled plugin installed, so setup could remove the working
basecamp@37signals while basecamp-cli sat disabled beside it. Setup now
removes the old ID only when the replacement is installed and enabled.

Also correct the legacy-key comments: during the window the marketplace
lists basecamp as an alias of basecamp-cli, not nothing at all.
Copilot AI balanced review requested due to automatic review settings October 7, 2026 01:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@jeremy

jeremy commented Oct 7, 2026

Copy link
Copy Markdown
Member Author

Review threads: 4 resolved (1 fixed, 3 declined, with the reasoning in each thread). CI is green on 917e451, and Codex reported no findings on it.

Fixed:

Declined:

Also in 917e451: the legacy-key comments now say the marketplace lists basecamp as an alias during the window. They used to say it lists no basecamp plugin.

Window: 7 days from the release that ships this, and the description now says so (it used to say 30). #857 tracks retiring the alias. The description also gives the merge and release order with basecamp/claude-plugins#8.

Copilot couldn't review dcd43bb or 917e451 because the requester hit its quota limit. Its last full review was on 795b275. A re-review has to be requested from the Reviewers UI.

@jeremy
jeremy merged commit f3bf0d8 into main Oct 7, 2026
30 of 31 checks passed
@jeremy
jeremy deleted the rename-plugin-basecamp-cli branch October 7, 2026 03:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

commands CLI command implementations docs plugin Claude Code plugin tests Tests (unit and e2e)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants