Skip to content

Add plugin system and interactive preset mode#23

Merged
nicksenap merged 5 commits intomasterfrom
feat/plugin-sys
Apr 3, 2026
Merged

Add plugin system and interactive preset mode#23
nicksenap merged 5 commits intomasterfrom
feat/plugin-sys

Conversation

@nicksenap
Copy link
Copy Markdown
Owner

Summary

  • Plugin system — external binary plugins (kubectl/git pattern). gw plugin install/list/upgrade/remove + automatic fallback for unknown commands (gw dash → finds gw-dash binary)
  • Interactive preset modegw create offers preset picker when presets exist, gw preset add/remove work interactively without flags
  • Clean picker cancel — Ctrl+C/Esc exits silently (exit 0) instead of error: selection cancelled across all picker call sites
  • gw-dash repo — scaffolded at nicksenap/gw-dash with Bubble Tea TUI, v0.1.0 released

Plugin details

Plugins are executables named gw-<name> found in ~/.grove/plugins/ or $PATH. Install from GitHub releases, pass context via env vars (GROVE_DIR, GROVE_CONFIG, GROVE_STATE, GROVE_WORKSPACE). Uses syscall.Exec on Unix for clean process handoff.

Security: size-limited extraction (256 MiB), HTTPS-only downloads, rate-limit-friendly GITHUB_TOKEN support.

Files

  • go/internal/plugin/ — plugin discovery, execution, install, upgrade (+ 15 unit tests)
  • go/cmd/plugin.go — cobra commands
  • go/cmd/root.go — unknown command → plugin fallback
  • go/cmd/create.go, go/cmd/preset.go — interactive preset picker
  • go/e2e/run.sh — 8 new e2e tests (70 total, all passing)
  • docs/plugins.md — plugin documentation

Test plan

  • gw plugin list — shows empty, then shows installed plugins
  • gw hello (with script in plugins dir) — falls back to plugin, passes env vars and args
  • gw plugin remove hello — deletes binary and metadata
  • gw nonexistent — shows error, exits 1
  • All 70 e2e tests pass
  • All 229 unit tests pass

🤖 Generated with Claude Code

nicksenap and others added 5 commits April 3, 2026 21:52
Plugins are executables named gw-<name> found in ~/.grove/plugins/ or
$PATH. Unknown commands automatically fall back to plugin lookup.

- gw plugin install <repo>: download from GitHub release
- gw plugin list/remove/upgrade: manage installed plugins
- Plugin metadata (.gw-<name>.json) tracks install source for upgrades
- Env vars (GROVE_DIR, GROVE_CONFIG, GROVE_STATE, GROVE_WORKSPACE)
  passed to plugins for context
- syscall.Exec on Unix for clean process handoff (TUI-friendly)
- e2e tests covering full plugin lifecycle

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Limit extracted binary size to 256 MiB (zip bomb protection)
- Limit GitHub API response body to 1 MiB
- Validate download URL is HTTPS before fetching
- Propagate plugin exit code on Windows instead of always exit(0)
- Skip os.Args[0] in pluginArgs to avoid false match on binary name
- Handle non-NotExist stat errors in Remove
- Strip http:// prefix in parseRepo

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- gw create: offer preset picker when presets exist, with "Pick manually…"
- gw preset add: interactive repo picker when --repos omitted
- gw preset remove: interactive picker when no name given
- Picker cancel (Esc/Ctrl+C) now exits cleanly (exit 0) instead of
  printing "error: selection cancelled" — applied across all 16 picker
  call sites via new exitOnPickerErr helper

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@nicksenap nicksenap merged commit d38a7a2 into master Apr 3, 2026
4 checks passed
@nicksenap nicksenap deleted the feat/plugin-sys branch April 3, 2026 20:10
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.

1 participant