0042 — Launch executor: a CLI verb that spawns an integration template
0042 — Launch executor: a CLI verb that spawns an integration template
TL;DR. phux launch <integration> resolves a named agent integration
template’s [launch] command from an enabled plugin’s integrations/
directory, expands the ${PHUX_PLUGIN_ROOT} placeholder into an absolute
argv, and spawns a pane running it through the existing SPAWN_TERMINAL
path. [launch] stays a field of the integration-template file (not the
phux-plugin.toml manifest); execution is child-process argv only — no
in-process host, no shell evaluation.
Status: Accepted Date: 2026-07-11
Context
The agent-tools plugin ships integration templates
(integrations/<id>.toml) that each declare a [launch] command wrapping
a real agent (claude/codex/gemini) through phux-agent-wrap.sh, so the
pane self-declares a phux.agent/v1 identity (ADR-0040). The r82.11 review
flagged the gap: nothing in phux read or ran that command, so installing
the plugin did not make an agent self-identify — a user still had to hand-run
the wrapper or alias it. This ADR closes the design space of what runs the
template’s [launch] command, and where that logic lives, under the
no-in-process-host constraint (vision.md / CONTRIBUTING.md).
Decision
- A CLI verb,
phux launch <integration> [-- extra args]. It resolves the integration to an argv and spawns a pane via the ordinarySPAWN_TERMINALwire op — the same pathphux spawnuses. No new wire frame; the server injectsPHUX_TERMINAL_IDinto the spawned pane exactly as for any spawn, so the wrapper self-targets with zero extra config. [launch]stays in the integration template, not the manifest. Integration templates are already a distinct, documented file format fromphux-plugin.toml. The launch executor resolves<id>by scanning each enabled plugin’sintegrations/*.toml(a convention, not a manifest-declared path) and matching the parsedid. A new typed model inphux-config(integration.rs) parses only the launcher-relevant fields (id,display_name,kind,[launch]) and ignores the rest, so the template stays a rich, forward-compatible package.${PHUX_PLUGIN_ROOT}expands to an absolute path before spawn. The pane runs the argv directly (no shell), so the placeholder is substituted per argv element into the owning plugin’s root. This is a plain string replace — nevereval/sh -c— so an untrusted field cannot inject extra arguments or commands.working_directorydecides the pane’s cwd, defaulting toworkspace(the directoryphux launchwas invoked from) so an agent runs where the human is;plugin-rootis available for programs that belong to the plugin tree.- Resolution is server-free and testable.
phux launch --print(a dry run) resolves and prints the argv without spawning;phux launch --listenumerates launchable integrations across enabled plugins.
Why
Reusing SPAWN_TERMINAL means the launcher composes for free with
PHUX_TERMINAL_ID injection (phux-w7mj) and pane recording — a launched
agent self-identifies end-to-end with no new server surface and no wire
change. Keeping [launch] in the template (rather than promoting it into
the plugin manifest) matches the existing split: a plugin ships templates,
and templates are versioned packages describing an external agent, not phux
entrypoints. Absolute-path expansion at resolution time is what lets the
wrapper script be found from any cwd while the agent still runs in the
user’s workspace — the exact wart the templates worked around before a
launcher existed.
Tradeoffs
- Scanning
integrations/per enabled plugin is O(templates) filesystem work on each launch; the directories are tiny, and only enabled plugins are scanned. - A broken sibling template is skipped so it cannot block a healthy launch; a parse error only surfaces when the requested id’s own file fails to parse. That trades a silent skip for robustness.
[launch]is not validated byphux plugin validate(that verb readsphux-plugin.toml, not templates); the launcher validates on resolution, and the demo plugin’svalidate-integrationsaction still checks the key’s presence.
Alternatives
Promote [launch] into phux-plugin.toml as a first-class manifest
section. Rejected: it would fold a versioned external-agent package format
into the phux plugin manifest, duplicate the template’s other sections
([detect], [session_identity], …), and couple manifest schema changes
to agent packaging. The template already owns this shape.
A [[panes]]-style manifest entrypoint the server auto-runs. Rejected:
that drifts toward phux executing plugin-declared programs implicitly; an
explicit phux launch verb keeps the human (or an agent) in control of when
a pane is spawned and composes with the palette/keybindings like any verb.
Shell-expand the [launch] command (sh -c). Rejected: it opens a
shell-injection surface over template fields for no benefit — the argv is
already structured, and per-element placeholder substitution covers the one
variable the templates need.