Skip to content

feat(plugin): help integration with --help-oneliner protocol (Phase 2)#190

Open
gwpl wants to merge 5 commits intosteipete:mainfrom
VariousForks:i188-external-plugin-discovery-phase2-help-integration
Open

feat(plugin): help integration with --help-oneliner protocol (Phase 2)#190
gwpl wants to merge 5 commits intosteipete:mainfrom
VariousForks:i188-external-plugin-discovery-phase2-help-integration

Conversation

@gwpl
Copy link

@gwpl gwpl commented Feb 6, 2026

Summary

Phase 2 of external plugin architecture (Issue #188). Builds on Phase 1 (#189).

Adds plugin discovery and help integration:

  • Plugins appear in gog --help under a new "Plugins:" section
  • Uses --help-oneliner protocol for plugin descriptions

Features

Plugin Discovery

  • Scans PATH for all gog-* binaries
  • Lazy discovery: only when help is requested
  • Deduplicates: first PATH occurrence wins

--help-oneliner Protocol

  • Plugins respond to --help-oneliner with single line (≤80 chars)
  • 100ms timeout keeps help responsive
  • Plugins without protocol support show no description

Help Integration

  • "Plugins:" section after "Commands:"
  • Aligned descriptions for readability
  • Colorized like built-in commands

Example Output

Commands:
  gmail <command> [flags]
    Gmail
  ...

Plugins:
  docs headings    List document headings with hierarchy and URLs
  hello            Say hello (example plugin)
  sheets formulas  Extract and analyze spreadsheet formulas

Example Plugin

#!/bin/bash
if [[ "$1" == "--help-oneliner" ]]; then
    echo "List document headings with hierarchy and URLs"
    exit 0
fi
# Plugin implementation...

Changes

  • internal/cmd/external.go - DiscoverExternalPlugins(), FetchOneliners()
  • internal/cmd/external_test.go - Tests for grouping and CommandName()
  • internal/cmd/help_printer.go - injectExternalPlugins(), colorization

Test plan

  • Unit tests for plugin grouping
  • Unit tests for CommandName()
  • Manual test with shell script plugins
  • Verified help output formatting
  • Verified colorization works

Dependencies

Depends on Phase 1: #189


Part of #188

Generated with Claude Code

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

gwpl and others added 5 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>
Add infrastructure for Phase 2 help integration:

* DiscoverExternalPlugins(): Scan PATH for all gog-* binaries
* FetchOneliners(): Query plugins with --help-oneliner flag
* GroupPluginsByTopLevel(): Group plugins by first subcommand
* ExternalPlugin struct with CommandName() helper

Protocol: Plugins respond to --help-oneliner with single line (≤80 chars).
Short 100ms timeout keeps help responsive; unresponsive plugins get no description.

Design notes in code:
- First PATH occurrence wins (matches exec.LookPath behavior)
- Plugins sorted alphabetically for consistent display

Unit tests document grouping and command name behavior.

Part of steipete#188

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Display discovered plugins in a "Plugins:" section after "Commands:".

Features:
* Lazy discovery: only scans PATH when help is requested
* Aligned output: plugin descriptions line up for readability
* Colorized: uses same styling as built-in commands
* Root help only: plugins not shown in subcommand help

Example output:
  Plugins:
    docs headings    List document headings with hierarchy and URLs
    hello            Say hello (example plugin)

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.

1 participant