Skip to content

feat(plugin): external command discovery (Phase 1 MVP)#189

Open
gwpl wants to merge 3 commits intosteipete:mainfrom
VariousForks:i188-external-plugin-discovery-phase1-mvp
Open

feat(plugin): external command discovery (Phase 1 MVP)#189
gwpl wants to merge 3 commits intosteipete:mainfrom
VariousForks:i188-external-plugin-discovery-phase1-mvp

Conversation

@gwpl
Copy link

@gwpl gwpl commented Feb 6, 2026

Summary

Implements Phase 1 MVP of cargo/git-style external command discovery (Issue #188).

When gog foo bar is invoked and Kong parsing fails (unknown command), the CLI now searches PATH for gog-foo-bar binary and executes it.

Design Decisions

1. Post-parse fallback (Option B) vs Pre-parse interception

Chosen: Post-parse fallback

Aspect Pre-parse (A) Post-parse (B)
Performance Slower for built-ins Faster for built-ins
Safety Plugins can shadow built-ins Built-ins always win

Why Option B: Built-in commands always take precedence over external plugins. This prevents accidental or malicious shadowing of core functionality and follows the git/cargo convention.

2. Longest-first (greedy) matching

For gog docs headings list, search order:

  1. gog-docs-headings-list (most specific)
  2. gog-docs-headings
  3. gog-docs

Why: More specific plugins should take precedence over generic ones.

3. Binary prefix: gog-*

Why: Matches the CLI binary name (following git → git-, cargo → cargo-).

Changes

  • internal/cmd/external.go - Discovery and execution logic
  • internal/cmd/external_test.go - Unit tests documenting behavior
  • internal/cmd/root.go - Integration into Execute()
  • docs/plans/2026-02-06-external-plugin-discovery-design.md - Design document

Test plan

  • Unit tests for longest-first matching (8 test cases)
  • Unit tests for error handling (not found, empty args)
  • Manual test with shell script plugins
  • Verified built-in commands still work

Example usage

# Create a plugin
echo '#!/bin/bash
echo "Hello from plugin!"
echo "Args: $@"' > ~/bin/gog-hello
chmod +x ~/bin/gog-hello

# Use it
gog hello world --flag
# Output:
# Hello from plugin!
# Args: world --flag

Future phases (separate PRs)

  • Phase 2: --help-oneliner protocol, help integration
  • Phase 3: Environment variable passing, caching

Closes #188 (Phase 1)


Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

gwpl and others added 3 commits February 6, 2026 13:06
Document Phase 1 MVP design for cargo/git-style external commands.
Key design decisions with rationale:

* Post-parse fallback (Option B): Built-in commands always take
  precedence over external plugins, preventing shadowing
* Longest-first matching: More specific plugins win over generic ones
* gog-* prefix: Matches CLI binary name (git/cargo convention)

Part of steipete#188

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement cargo/git-style external command discovery:

* Search PATH for gog-{subcommands} binaries
* Longest-first (greedy) matching: gog-docs-headings wins over gog-docs
* Pass remaining args to plugin
* Use syscall.Exec for true process replacement

Design rationale documented in code comments:
- Longest-first: More specific plugins take precedence
- gog-* prefix: Matches CLI binary name (following git/cargo)

Unit tests document and verify the matching behavior.

Part of steipete#188

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Hook external command discovery into Kong parse error handling:

* Try external command AFTER Kong parsing fails (post-parse fallback)
* If found: exec replaces current process
* If not found: return original Kong error

Design choice: Post-parse fallback (Option B)
Why: Built-in commands always take precedence over external plugins.
This prevents accidental or malicious shadowing of core functionality
and follows the git/cargo convention.

Part of steipete#188

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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.

Proposal: Extensible Plugin Architecture (cargo/git-style external commands)

1 participant