Skip to content

Ship wp-ops as a trellis-cli plugin (trellis ops) - #188

Merged
jasperf merged 4 commits into
mainfrom
feature/trellis-cli-plugin
Aug 21, 2026
Merged

Ship wp-ops as a trellis-cli plugin (trellis ops)#188
jasperf merged 4 commits into
mainfrom
feature/trellis-cli-plugin

Conversation

@jasperf

@jasperf jasperf commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Version: 5.6.0

This release adds a trellis-cli plugin integration for wp-ops, exposing the full command catalog as trellis ops <...> without any new plugin API, separate binary, or additional repository. trellis-cli discovers plugins by scanning $PATH for trellis-* executables and exec'ing them with the remaining argv, so the entire integration is a second symlink to the same binary — the Homebrew cask now installs trellis-ops alongside wp-ops via a custom_block in .goreleaser.yml. A new go/cmd/invoked.go reads filepath.Base(os.Args[0]) to detect which name was used, and every help string, usage line, and did-you-mean suggestion across root.go, list.go, dispatch.go, docs.go, search.go, and serverside.go now renders against that name rather than a hardcoded wp-ops. Under trellis ops, listing views scope to the 27 commands tagged @platform trellis across 6 categories instead of the full 74, while execution and --json output remain deliberately unscoped. Output under bare wp-ops is byte-for-byte unchanged, and the change is covered by 92 lines of new tests in go/cmd/invoked_test.go.

Plugin Integration and Packaging:

  • Added a trellis-ops symlink to the Homebrew cask (.goreleaser.yml), making every wp-ops command reachable as trellis ops <...> from inside trellis-cli. The name must be exactly trellis-ops: the finder splits on - and joins remaining segments with spaces, so trellis-wp-ops would register as the three-word trellis wp ops.
  • Documented the manual fallback (ln -s "$(command -v wp-ops)" /usr/local/bin/trellis-ops) for source builds, along with the trellis-cli v1.19.0+ and load_plugins: true requirements.
  • Plugins register from $PATH before trellis-cli resolves a project, so trellis ops runs anywhere; playbook commands continue to locate the Trellis directory through wp-ops's own detect.TrellisDir.

Invocation-Aware CLI Behavior:

  • Converted rootCmd.Long from a literal string into rootLong(name), a template rendered at Execute() time with column-40 alignment preserved and a guard for the wider trellis ops prefix.
  • Added defaultPlatform(), which applies an implicit @platform trellis filter to listing views when invoked as a plugin; an explicit --platform flag always overrides it.
  • Categories with no Trellis-tagged commands (SEO, Images, Git) fall back to listing in full with an explanatory note, rather than appearing empty.
  • Scoping is confined to what is advertised: command dispatch never filters by platform, and --json returns the complete catalog since it serves as a contract for external tooling.

Documentation:

  • Added a README section covering plugin usage, the listing/execution scoping distinction, and installation requirements.
  • Recorded the 5.6.0 entry in CHANGELOG.md with the trellis-cli discovery mechanics and naming constraints, including why ops was chosen (segments matching core root commands are silently skipped by isUnderCoreRootCommands).
  • Revised docs/trellis-extensions-evaluation.md (139 lines changed) to reflect the implemented plugin approach.

Files Changed:

jasperf and others added 4 commits August 21, 2026 09:25
trellis-cli registers any executable on $PATH named `trellis-*` as a
subcommand and execs it with the remaining argv, so shipping wp-ops as a
`trellis ops` plugin needs no plugin API — just a second name for the same
binary. What it does need is for the binary to notice which name it was
called under.

Two things followed from that, both keyed off filepath.Base(os.Args[0]):

Help text and suggestions now render against the invoked name. Telling
someone who typed `trellis ops` to "Run 'wp-ops backup'" points them at a
command they may not know exists. Root's Long help became a template
(rootLong) rather than a literal string; output under bare wp-ops is
byte-for-byte what it was.

Listing views scope to @platform trellis under the plugin name — 27
commands across 6 categories instead of all 74. Someone at a `trellis`
prompt is not looking for the image converters or the release scripts.
Deliberately narrow: an explicit --platform wins, a category with nothing
Trellis-tagged still lists in full rather than claiming to be empty,
--json stays the whole catalog because it is a contract for external
tooling, and execution is never scoped — name any command and it runs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LEJsmBJKcH4dXK3LUDr6zN
The entire trellis-cli integration is a second symlink to the same
binary. wp-ops ships as a goreleaser-generated cask, so it belongs in
.goreleaser.yml rather than hand-edited into imagewize/homebrew-tap,
whose Casks/wp-ops.rb is stamped "DO NOT EDIT".

homebrew_casks has no field for a second `binary` stanza with a target,
so this goes through custom_block. Verified by rendering the cask with a
snapshot build.

The name must be exactly `trellis-ops`: the plugin finder splits the
filename on "-", drops the first segment, and joins the rest with spaces,
so `trellis-wp-ops` would register the three-word `trellis wp ops`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LEJsmBJKcH4dXK3LUDr6zN
README gains a "trellis-cli plugin" section under the CLI docs, including
the manual symlink for people who build from source rather than
installing the cask.

trellis-extensions-evaluation.md's Path A was written as a proposal and
recommended the name `trellis-wpops`. Rewritten to describe what actually
shipped as `trellis ops`, with the cask mechanics that the original
(which assumed a formula) got wrong, and the verified finding that plugin
commands run outside a Trellis project while core ones do not.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LEJsmBJKcH4dXK3LUDr6zN
New feature, nothing breaking, so a minor bump. The version is read out of
CHANGELOG.md's first `## [X.Y.Z]` heading at runtime (go/cmd/version.go
getVersion, go/cmd/env.go embeddedVersion), so this heading is the whole
bump — there is no second copy to keep in sync.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LEJsmBJKcH4dXK3LUDr6zN
@jasperf
jasperf merged commit ee660a9 into main Aug 21, 2026
1 check passed
@jasperf
jasperf deleted the feature/trellis-cli-plugin branch August 21, 2026 02:38
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