Skip to content

Add headless open <name> subcommand#47

Merged
cloudmanic merged 1 commit into
mainfrom
feat/headless-open-subcommand
Jul 23, 2026
Merged

Add headless open <name> subcommand#47
cloudmanic merged 1 commit into
mainfrom
feat/headless-open-subcommand

Conversation

@cloudmanic

Copy link
Copy Markdown
Owner

What

Adds a headless open <name> subcommand so a project's workspace can be opened by name, without the interactive fuzzy picker:

herdr-plus open harbor-sysadmin

This is the scriptable entry point the picker never gave us — for shell aliases, keybindings, and AI agents that want to spin up a known workspace in one shot.

How

  • main.go — registers the open subcommand.
  • open.gorunOpen loads the project templates, resolves the name via findProject (exact match first, then a case-insensitive fallback; a miss errors with the list of available projects), and hands the project to the existing openProject — the exact code path the picker runs on Enter. So the template → workspace layout has a single source of truth regardless of how it's opened.
  • Config discovery — when herdr runs us as a plugin it injects HERDR_PLUGIN_CONFIG_DIR, but a direct herdr-plus open ... from a shell has no such injection, so config would look in the standalone ~/.config/herdr-plus and miss the managed templates. ensureManagedConfigDir asks the running herdr (herdr plugin config-dir <id>) for its managed dir and exports it — doing exactly what herdr would have done — so open finds the same templates the picker shows. configBaseDir is intentionally left untouched (the picker path already short-circuits on the injected env var).
  • util.go — a shared pluginID constant, also swapped into the existing --plugin call sites in projects.go / quickactions.go.
  • README — documents the subcommand under Projects.

Testing

  • open_test.go covers findProject (all resolution paths) and the config-dir discovery helpers, using a fake herdr located via HERDR_BIN_PATH so the tests stay deterministic with no real herdr present.
  • go build ./..., go vet ./..., and go test -race ./... all pass locally.
  • Manually verified end-to-end against a running herdr: usage/not-found error paths, managed-dir discovery (bogus name now lists all projects), and a real open dotfiles that materialized the full 4-tab workspace.

Notes

  • Version is intentionally not bumped — the release pipeline auto-bumps the patch on merge.
  • open is a direct-invocation subcommand, not a manifest action (actions take fixed commands, so they can't accept a runtime <name>).

Open a project's workspace by name without the interactive fuzzy picker.
runOpen reuses the picker's openProject, so a template's layout has a
single source of truth whether it's opened via the browser or by name.

- main.go: register the `open` subcommand
- open.go: runOpen + findProject (exact match, case-insensitive fallback,
  helpful "available projects" error). A direct invocation has no
  HERDR_PLUGIN_CONFIG_DIR injected, so ensureManagedConfigDir asks the
  running herdr (`herdr plugin config-dir <id>`) for its managed config
  dir and exports it — finding the very same templates the picker shows.
- util.go: shared pluginID constant, also swapped into the existing
  --plugin call sites in projects.go and quickactions.go.
- open_test.go: cover findProject and the config-dir discovery helpers
  (a fake herdr via HERDR_BIN_PATH keeps them deterministic offline).
- README: document `herdr-plus open <name>`.
@cloudmanic
cloudmanic merged commit e269642 into main Jul 23, 2026
2 checks passed
@cloudmanic
cloudmanic deleted the feat/headless-open-subcommand branch July 23, 2026 16:44
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