Skip to content

feat: plugin auto-disable + CLI commands (Phase 2.5 & 3.1)#131

Merged
github-actions[bot] merged 2 commits into
developfrom
feature/roadmap-phase2-3
Mar 12, 2026
Merged

feat: plugin auto-disable + CLI commands (Phase 2.5 & 3.1)#131
github-actions[bot] merged 2 commits into
developfrom
feature/roadmap-phase2-3

Conversation

@tomymaritano

@tomymaritano tomymaritano commented Mar 12, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Auto-disable crashing plugins: PluginRegistry now auto-disables plugins after 3 consecutive crashes, with resetErrors() for manual re-enable and isAutoDisabled() query
  • Plugin CLI commands: Added list, install, uninstall, and link commands to readied-plugin CLI for managing community plugins from the terminal
  • Cross-platform utils: Shared getPluginsDir() resolves macOS/Win/Linux plugin directories

Test Plan

  • All 235+ tests pass (pnpm test)
  • Auto-disable tests: threshold enforcement, reset behavior, pre-threshold behavior
  • Manual: readied-plugin list shows installed plugins
  • Manual: readied-plugin link . creates symlink for dev plugins

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added crash threshold protection that automatically disables plugins after repeated failures
    • Introduced plugin error state reset capability for recovery
    • Added CLI commands for plugin management: list (view installed plugins), install (add from archive or directory), uninstall (remove safely with confirmation), and link (for local development)

- Add auto-disable after 3 crashes in PluginRegistry with
  resetErrors() and isAutoDisabled() methods
- Add plugin CLI commands: list, install, uninstall, link
- Cross-platform plugins directory resolution
- Tests for auto-disable behavior

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Mar 12, 2026

Copy link
Copy Markdown

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

This PR introduces plugin lifecycle management and a comprehensive CLI suite. It adds crash-threshold auto-disable functionality to PluginRegistry with error reset/query APIs, and implements four new CLI commands (list, install, uninstall, link) for plugin management with supporting utilities for directory resolution and manifest validation.

Changes

Cohort / File(s) Summary
Plugin Registry Lifecycle
packages/plugin-api/src/lifecycle/PluginRegistry.ts
Adds MAX_CRASH_COUNT constant, crash guard in activate() method, and public APIs resetErrors() and isAutoDisabled() for error state management and auto-disable status querying.
Plugin Registry Tests
packages/plugin-api/tests/registry.test.ts
Adds tests for auto-disable-on-crash behavior, error reset flow, and crash threshold scenarios; imports MAX_CRASH_COUNT from PluginRegistry.
CLI Infrastructure
packages/plugin-cli/src/cli.ts, packages/plugin-cli/src/utils.ts
Adds list, install, uninstall, and link command routing in main CLI; introduces getPluginsDir(), PluginManifest interface, and readManifest() utility for cross-platform plugin directory management and manifest validation.
List Command
packages/plugin-cli/src/commands/list.ts
Implements listPlugins() to enumerate installed plugins, read manifests, and output formatted table with ID, name, version, and symlink status.
Install Command
packages/plugin-cli/src/commands/install.ts
Implements installPlugin(source) to validate, extract archives (.tar.gz, .tgz, .zip) or local directories, locate plugin root, validate manifest, check for duplicates, and copy plugin to plugins directory with cleanup.
Uninstall Command
packages/plugin-cli/src/commands/uninstall.ts
Implements uninstallPlugin(pluginId) to validate plugin ID, detect symlinks, prompt user confirmation, and remove plugin or symlink with appropriate error handling.
Link Command
packages/plugin-cli/src/commands/link.ts
Implements linkPlugin(source) to create filesystem symlink from local plugin source to plugins directory for development, validating manifest and detecting existing installations.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main changes: plugin auto-disable feature and new CLI commands, referencing the specific roadmap phases being addressed.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/roadmap-phase2-3

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@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: 658f750e36

ℹ️ 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".

const resolvedPluginsDir = resolve(pluginsDir);
if (
!resolvedPluginDir.startsWith(resolvedPluginsDir + '/') &&
resolvedPluginDir !== resolvedPluginsDir

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Reject plugins root path in uninstall validation

The safety check allows resolvedPluginDir === resolvedPluginsDir, so readied-plugin uninstall . is treated as valid and the later rmSync(pluginDir, { recursive: true, force: true }) call removes the entire plugins directory instead of a single plugin. This is a destructive data-loss path reachable from normal CLI input and should be blocked by requiring the uninstall target to be a strict child of the plugins directory.

Useful? React with 👍 / 👎.

const resolvedPluginDir = resolve(pluginDir);
const resolvedPluginsDir = resolve(pluginsDir);
if (
!resolvedPluginDir.startsWith(resolvedPluginsDir + '/') &&

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Compare uninstall paths with OS-aware separator

The containment check hardcodes '/' in resolvedPluginsDir + '/', but on Windows resolve() returns backslash-separated paths, so valid plugin paths fail startsWith(...) and uninstall exits with "Invalid plugin ID." for every plugin. This makes the new uninstall command unusable on Windows.

Useful? React with 👍 / 👎.

}

const pluginsDir = getPluginsDir();
const targetDir = join(pluginsDir, manifest.id);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Constrain manifest.id before deriving install target

The installer builds targetDir directly from join(pluginsDir, manifest.id) without validating that manifest.id is a safe path segment, while readManifest() accepts any non-empty string. A crafted manifest id like ../somewhere will resolve outside the plugins directory, allowing archive installs to copy files into arbitrary user-writable locations.

Useful? React with 👍 / 👎.

@tomymaritano

Copy link
Copy Markdown
Collaborator Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Mar 12, 2026

Copy link
Copy Markdown
✅ Actions performed

Full review triggered.

@github-actions github-actions Bot enabled auto-merge (squash) March 12, 2026 02:47
@github-actions github-actions Bot merged commit 8dc7079 into develop Mar 12, 2026
11 of 12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant