Skip to content

feat(claude): install as a native plugin, skills plugin-only - #38

Closed
camjac251 wants to merge 1 commit into
tolibear:mainfrom
camjac251:feat/claude-native-plugin
Closed

feat(claude): install as a native plugin, skills plugin-only#38
camjac251 wants to merge 1 commit into
tolibear:mainfrom
camjac251:feat/claude-native-plugin

Conversation

@camjac251

@camjac251 camjac251 commented Jul 23, 2026

Copy link
Copy Markdown

Summary

  • npx goalbuddy now installs GoalBuddy on Claude Code as a native plugin (claude plugin marketplace add + claude plugin install --scope user), matching the Codex native-plugin model. The plugin surfaces the $goal-prep skill, the Scout/Judge/Worker subagents, and the /goal command from its own versioned cache, so a clean install no longer scatters loose files under ~/.claude/{skills,agents,commands}. The installer removes any left from an earlier version.
  • Claude is plugin-only for skills, agents, and the /goal command. There is no loose-file fallback. When the claude CLI is not on PATH (or the plugin install fails), the installer writes no loose files, reports an unmanaged result, and prints how to finish from inside Claude Code (/plugin marketplace add + /plugin install). It never writes a loose ~/.claude/skills/goal-prep, so nothing leaks into Codex through a ~/.agents/skills symlink. It also never wipes a working install it cannot replace: any pre-existing loose files are left in place and reported, and clear only on a successful plugin install or reset. Only files GoalBuddy itself wrote are ever removed (matched by a content marker), so a user's own ~/.claude/commands/goal.md is never touched. The Codex side still succeeds in an install-everywhere run, and a failed codex plugin marketplace add (no codex CLI, offline, or a private or rate-limited clone) is recorded as a warning rather than aborting, so the bundled cache, config, and agents still install.
  • Updates stay the user's choice. The installer installs and enables the plugin but does not enable marketplace auto-update. This matches Codex and how Claude Code treats third-party marketplaces. npx goalbuddy update remains the reliable cross-harness updater; users opt into auto-update in /plugin. GoalBuddy writes none of your Claude config: nothing writes settings.json or known_marketplaces.json, and doctor only reads them.
  • reset --target claude delegates removal to the claude CLI (plugin uninstall + marketplace remove) and only cleans loose leftovers itself. doctor --target claude reports plugin state straight from installed_plugins.json (works with or without the CLI) and flags any loose leftovers; it resolves the plugin store from CLAUDE_CODE_PLUGIN_CACHE_DIR when that override is set, matching the claude CLI.
  • Release automation: an npm version lifecycle hook (sync-manifest-version.mjs) stamps both plugin.json versions from package.json, so a release keeps all three in lockstep in one commit and tag.
  • Cleanup: removed the loose Claude install path (skill/agents/command writers plus their fingerprint and metadata helpers) and a dead install-path subtree (installAll, installSkill, compatibilitySkillBody, printInstallReport), and pulled the default marketplace source into one constant.

Why

Third-party marketplaces default auto-update off, so a plugin-installed Claude user could silently freeze on an old version (this happened in practice). The fix keeps the plugin self-contained and puts the update decision with the user.

Claude skills are plugin-only for a second, verified reason. Codex reads standalone skills from ~/.agents/skills and dedupes by SKILL.md path, not by name (core-skills/src/loader.rs skill_roots_from_layer_stack_inner + root_loader.rs). A loose ~/.claude/skills/goal-prep reached through a ~/.agents/skills symlink therefore surfaces a second, duplicate goal-prep in Codex alongside the plugin's goalbuddy:goal-prep. Refusing to write loose Claude files closes that leak.

Codex cannot be made equally self-contained: Codex plugins surface skills, MCP servers, hooks, and apps, but not subagents, so the three ~/.codex/agents/*.toml files must live outside the plugin (verified against codex-rs). That asymmetry is a platform requirement, not a choice.

Test plan

  • npm run check internal suite passes (121 internal tests). The local-board tests fail only in the sandbox (loopback networking) and pass in CI.
  • New coverage: native install with the exact command sequence, the upgrade path (old version to packaged version), no loose files written when the CLI is absent (reports unmanaged), a pre-existing loose install preserved when plugin install fails, legacy loose dirs cleaned on a successful native install, the provenance guard sparing a user's own same-named files, the agents command pointing at the plugin, doctor passing without the CLI and failing when loose files are present, settings.json left untouched, CLAUDE_CONFIG_DIR resolution, reset delegating to the CLI, the manifest --write stamping path, the Codex install completing when marketplace add fails, and doctor resolving the plugin store from CLAUDE_CODE_PLUGIN_CACHE_DIR.
  • Live smoke test against a throwaway --claude-home before publish.

Notes

  • No loose-file fallback: without the claude CLI the installer reports unmanaged and points at /plugin. This is deliberate, to keep GoalBuddy's Claude skill from leaking into Codex via ~/.agents/skills.
  • Ships in the 0.5.0 minor release. The changelog stays under Unreleased until then; the release step runs npm version minor, which stamps package.json and both plugin.json manifests via the hook.

npx goalbuddy installs GoalBuddy on Claude Code as a native plugin
(claude plugin marketplace add + install --scope user), matching the Codex
model. The plugin surfaces the goal-prep skill, the Scout/Judge/Worker
subagents, and the /goal command from its own versioned cache.

There is no loose-file fallback. When the claude CLI is unavailable or the
plugin install fails, the installer writes no loose files, reports an
unmanaged result, and points at /plugin. Codex loads standalone skills from
~/.agents/skills and dedupes by SKILL.md path, so a loose
~/.claude/skills/goal-prep reached through a ~/.agents/skills symlink
surfaced a duplicate skill in Codex next to the plugin's goalbuddy:goal-prep.
Not writing loose Claude files closes that leak.

Cleanup only removes files GoalBuddy authored (content-marker guard) and only
on a successful install or reset, so a user's own goal.md is never deleted and
a transient failure never wipes a working setup. doctor reports plugin state
from installed_plugins.json (works without the CLI) and flags loose leftovers.
Updates stay the user's choice: the installer never enables marketplace
auto-update or writes settings.json / known_marketplaces.json.

The Codex install tolerates a failed marketplace registration: the plugin
content is bundled and Codex loads from the cache dir plus the [plugins]
config, so a failed `plugin marketplace add` (no codex CLI, offline, or a
private or rate-limited clone) records a warning and the cache, config, and
agents still install. doctor resolves the Claude plugin store from
CLAUDE_CODE_PLUGIN_CACHE_DIR when that override is set, matching the claude
CLI, so it reads the same files the CLI wrote.
@camjac251
camjac251 force-pushed the feat/claude-native-plugin branch from 4820949 to 8b3f0ee Compare July 23, 2026 22:06
@tolibear

tolibear commented Aug 5, 2026

Copy link
Copy Markdown
Owner

Thank you for the deep investigation and for documenting the no-loose-file rationale so carefully. I am closing this version because it is now four mainline changes behind, conflicts with current main, has no completed live smoke test, and still installs the GoalBuddy execution command as /goal, which 0.4.3 intentionally moved to /goalbuddy to preserve Claude Code's native command.

The native Claude plugin direction may still be worth revisiting, but it should come back as a fresh, smaller PR against current main with /goalbuddy, a real throwaway-home smoke test, and migration behavior separated from the install-model change. That will make the destructive cleanup and compatibility boundary much easier to review safely.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants