Skip to content

Launching ​

The bare invocation is the launch — hyprpilot is one binary, there is no run subcommand, and the profiles and mcp subcommands round out the surface:

sh
hyprpilot [PROFILE] [flags] [-- <provider args>]
hyprpilot profiles [--json]
hyprpilot mcp serve                          # general tools (`open`)
hyprpilot mcp skills [--skill-dir <json>]…   # the skill catalogue and prompts
hyprpilot mcp harness [--max-sessions <n>]   # spawn/drive agent sessions
hyprpilot mcp passthrough [--tool <json>]…   # declared tools forwarded to HTTP endpoints

Picking a profile ​

The profile is an optional positional argument — no --profile/-p flag:

sh
hyprpilot                       # interactive picker over configured profiles
hyprpilot engineer              # launch the `engineer` profile directly

Omit the positional and an interactive fuzzy picker (powered by nucleo) opens over your configured profiles — each row shows the default marker, id, agent, model, and cwd. The profile.default entry starts pre-selected under the cursor, so a bare hyprpilot followed by Enter launches your default. Cancelling the picker aborts the launch; a non-interactive terminal errors instead of hanging.

Because subcommands resolve before the positional, hyprpilot profiles and hyprpilot mcp always run the subcommand — a profile literally named profiles or mcp is therefore not positionally addressable (rename it, or reach it through profile.default + the picker).

Launch flags ​

FlagPurpose
[PROFILE]Positional session-profile id to resolve and launch. Omit to pick interactively.
-p, --prompt <PROMPT>Inline headless prompt — the non-pipe alternative to echo … | hyprpilot. Forces headless.
-f, --file <PATH>Read the headless prompt from a file (~ / $VAR / relative expanded). Mutually exclusive with --prompt.
--cwd <dir>Working directory for the vendor process.
--mode <mode>Mode override, projected onto the vendor where supported.
--resume[=<session>]Continue a conversation — bare opens the vendor's session picker, with a value it resumes that session.
--resume-lastContinue the most recent conversation, no picker. Mutually exclusive with --resume.
--with-config <path|@inline|->Profile overlay patch (repeatable). See Ad-hoc Overlays.
--with-config-format <toml|json|yaml>Format for stdin / inline / extension-less overlays (default json).
-- <args>Everything after -- is forwarded verbatim to the vendor CLI; generated equivalents are suppressed.

Overriding per launch ​

The profile is the single source of truth for its agent and model — there are no --agent / --model launch flags. The two per-launch knobs that remain touch only where the vendor runs and how, not what the profile is:

sh
hyprpilot engineer --cwd ~/code/foo   # run somewhere else
hyprpilot engineer --mode plan        # vendor-specific mode
  • --cwd <dir> beats the profile's (or agent's) configured cwd; when neither speaks, the current directory is used.
  • --mode is projected onto the vendor CLI where supported.

For a one-off model, agent, MCP set, or system prompt — anything that changes what the profile resolves to — reach for --with-config, the ad-hoc overlay escape hatch:

sh
hyprpilot engineer --with-config '@{"model":"claude-opus-4-5"}'  # different model, one launch
hyprpilot engineer --with-config '@{"agent":"codex"}'            # different agent, one launch

Resuming a conversation ​

--resume and --resume-last are vendor-neutral: hyprpilot maps the intent onto whatever the resolved profile's vendor calls it, so one keybinding works across every profile.

sh
hyprpilot engineer --resume              # pick a session in the vendor's own picker
hyprpilot engineer --resume-last         # straight back into the most recent one
hyprpilot engineer --resume=<session-id> # a specific session
Intentclaudecodexopencodeamp
Picker--resumeresumeunsupportedthreads continue
Most recent--continueresume --last--continuethreads continue --last
By session id--resume <id>resume <id>--session <id>threads continue <id>

Two refusals, both loud rather than silent:

  • opencode has no session picker. Its CLI registers only --continue and --session <id>, so a bare --resume errors instead of quietly resuming something you did not choose.
  • No picker survives a headless launch. A picker needs a terminal to answer it, so combining --resume with --prompt / --file / piped stdin errors. Use --resume-last or --resume=<session-id> there.

Passing the vendor's own flag through -- <args> still wins — the generated projection is suppressed exactly as it is for every other flag.

Codex headless resumes use codex exec <launch options> resume <session-id|--last> <provider args>. The profile's native args and generated model, effort, instructions, MCP, cwd and sandbox settings stay on the parent exec command, including on harness session_send follow-ups. Parent-only flags such as --profile, --approve-for-me, --cd and --sandbox are not accepted after exec resume; put native launch settings in the profile's args. Trailing -- <args> remain verbatim resume arguments, such as --all or --model <model>.

Forwarding native arguments ​

Everything after a -- separator is forwarded verbatim to the vendor CLI — use it for provider-native flags and resume flows:

sh
hyprpilot engineer -- --resume
hyprpilot review -- --dangerously-skip-permissions

Any provider-native argument you pass this way suppresses hyprpilot's generated equivalent, so your hand-written flag always wins over the projection.

Running the bare command ​

hyprpilot run resolves a profile like a launch, patches and overlays included, then runs its command with the profile's environment and only the arguments after --. Nothing is projected: no model, mode, system prompt, MCP servers or prompt, and not the agent's own args. Use it for the vendor's account and maintenance subcommands, which then land in the same config and login folders the profile's launches use:

sh
hyprpilot --config-profile work run claude/opus -- setup-token
hyprpilot --config-profile work run amp/high -- login
hyprpilot --config-profile personal run codex/gpt-6-luna -- login

Omit the profile to pick one interactively. Launch flags such as --cwd, --mode and --with-config do not apply and are rejected; the profile's configured cwd still does.

Headless / prompt delivery ​

Give hyprpilot a prompt and it launches the vendor non-interactively — one shot, then exit, like claude --print. There are three ways to supply the prompt:

sh
echo "fix the failing test" | hyprpilot engineer   # piped stdin
git diff | hyprpilot review                         # the diff becomes the prompt
hyprpilot engineer --prompt "fix the failing test"  # inline flag, no pipe needed
hyprpilot engineer --file ./task.md                 # prompt read from a file

Headless is effective when any of these is true: --prompt / --file is given, the profile sets headless = true, or stdin is a pipe (not a TTY). The prompt source resolves in priority order — an explicit --prompt / --file value wins over piped stdin (--prompt and --file are mutually exclusive; passing both errors).

The full model / effort / mode / MCP / tool-policy projection — plus --cwd, --mode, and --with-config — still applies; headless only changes how the prompt is delivered, not what the profile resolves to.

How the prompt reaches the vendor ​

hyprpilot delivers the resolved prompt on the vendor's stdin where the vendor supports it, and as a positional argument otherwise:

VendorProjected invocationPrompt delivery
claudeclaude --print (prompt on stdin)stdin (spawned, then EOF)
codexcodex exec (prompt on stdin)stdin (spawned, then EOF)
opencodeopencode run "<prompt>"positional argument
ampamp --execute (prompt on stdin)stdin (spawned, then EOF)

For claude, codex and amp, hyprpilot spawns the vendor, writes the prompt to its stdin, and closes the pipe (EOF). This is deliberate: claude's --allowedTools / --disallowedTools are variadic flags that would greedily swallow a trailing positional prompt as a tool entry, and a positional never reaches the model; stdin has no such ambiguity. opencode has no stdin prompt support (its run [message…] is positional-only), so the prompt stays a positional argument there. The interactive (non-headless) path always exec()s, unchanged.

  • Profile selection. A headless launch never opens the interactive picker (there may be no TTY, and stdin may be a consumed pipe). With no positional profile it resolves profile.default directly, and errors cleanly when no default is configured — pass a positional profile or set a default.

  • Headless without a prompt. If headless is forced (profile headless = true, or --prompt/--file — though those always carry a prompt) but no prompt resolves — e.g. headless = true on an interactive TTY with no pipe and no --prompt/--file — the launch errors rather than opening a picker it can't drive. An empty prompt (empty pipe, or empty --prompt/--file) errors too.

  • --with-config - already drains stdin. --with-config - reads the pipe to build the overlay, so the same pipe can't also be the headless prompt. Piping into a headless launch that also passes --with-config - errors with a targeted message (rather than misreporting an "empty prompt") — pass the prompt via --prompt / --file instead, or forward it through a trailing -- <provider args>.

  • Escape hatch — bring your own invocation. When you pass the vendor's headless flags yourself via -- … without a --prompt/--file, hyprpilot does not read stdin — fd0 stays inherited so the vendor gets the raw pipe as input data, and the trailing args suppress hyprpilot's generated projection:

    sh
    cat data.json | hyprpilot engineer -- -p "summarize this"
    # → claude gets data.json on stdin AND "summarize this" as the prompt arg

    Only the automatic path (no trailing -- args) buffers stdin.

  • -p/-f compose with -- <provider args>. An explicit --prompt / --file is a deliberate prompt, so it is delivered even when you also pass trailing -- <provider args> — the two compose rather than being mutually exclusive. hyprpilot delivers the prompt on its usual vendor path (stdin for claude / codex, positional for opencode) and appends your -- <args> to the vendor argv, where the existing dedup lets a hand-passed flag suppress hyprpilot's generated equivalent:

    sh
    hyprpilot engineer -p "fix the bug" -- --allowedTools Read
    # → claude gets "fix the bug" on stdin AND `--allowedTools Read` on argv

    Only the escape hatch without an explicit --prompt/--file skips stdin entirely.

Global flags ​

Available on every invocation, each with an environment twin, so you can pin them per shell or per session:

FlagEnvPurpose
--config <path>HYPRPILOT_CONFIGOverride the global config path (format inferred from the extension).
--config-profile <name>HYPRPILOT_CONFIG_PROFILELayer a named config-layer overlay (profiles/<name>.{ext}). Repeatable; the env var takes a comma-separated list.
--log-level <level>HYPRPILOT_LOG_LEVELOverride the tracing filter (trace / debug / info / warn / error).
sh
HYPRPILOT_CONFIG_PROFILE=work hyprpilot engineer

--config-profile layers a named config file (~/.config/hyprpilot/profiles/<name>.yaml) on top of your global config — a config-layer profile, distinct from the session profiles you address with the positional [PROFILE]. Pass it more than once (or HYPRPILOT_CONFIG_PROFILE=base,work) to stack overlays; they fold in the given order. See Config → Layering.

--select-config-profile picks the overlay interactively instead, from the files under ~/.config/hyprpilot/profiles/, before the session profile is resolved. It replaces whatever --config-profile or HYPRPILOT_CONFIG_PROFILE selected, with that selection under the cursor, and the pick follows the launch into the Agent Harness like any other. It is launch-only and needs an interactive terminal.

hyprpilot completion <shell> prints the shell completion script — see Installation → Shell completion.

Log filter precedence is --log-level → RUST_LOG → logging.level → the built-in error default (a fresh run is quiet — errors only — unless a level is explicitly requested); tracing always writes to stderr. See Config → Logging.

cwd reaches each vendor differently. claude inherits the process working directory; codex takes --cd; opencode reads $PWD before the process working directory. hyprpilot sets the process cwd and whatever else the vendor reads — --cd for codex, PWD in opencode's env. $PWD is otherwise inherited from the shell that started hyprpilot, so an opencode agent given a cwd silently worked in the caller's tree while every surface reported the requested path, and opencode run has no --dir flag to say it instead. A --cd you pass yourself after -- suppresses the generated one.

What a launch does ​

  1. Load + validate layered config (Config → Layering).
  2. Pick the profile (positional [PROFILE] → profile.default → picker) and fold patches + --with-config overlays.
  3. Build the per-launch MCP + skills registries, auto-injecting each in-tree server your mcp config enables (Skills, Agent Harness, HTTP Passthrough).
  4. Project everything onto the vendor's native flags/env (Config → Agents).
  5. Optionally rename the tmux window / zellij tab (Config → Multiplexer).
  6. exec() — the vendor CLI replaces the hyprpilot process.

cwd precedence ​

The working directory the vendor launches in resolves as: explicit --cwd flag → the profile's (or agent's) configured cwd → the current directory. A profile pinned to a repo therefore launches there by default, and --cwd overrides it per invocation.

Inspecting without launching ​

sh
hyprpilot profiles              # table: default marker, profile, agent, model
hyprpilot profiles --json       # machine-readable
hyprpilot --with-config '@{"model":"claude-opus-4-5"}' profiles   # preview an overlay

The listing resolves config the same way a launch does — including patches and any --with-config overlay you pass — but stops before exec, so the displayed summaries reflect what a launch would use. --json keeps stdout pure (all tracing goes to stderr), safe to pipe into jq.

If a patches / --with-config overlay fails to resolve for a profile, that row is flagged with a ! marker and the error message (in the table, the JSON gains an error field) instead of silently showing the un-overlaid base values — so a broken patch is never mistaken for the resolved shape.

An empty profiles list is a validation error, not an empty table — fresh installs refuse to run until you configure at least one profile (Quickstart). A config typo aborts with an error naming the offending field path.

Subcommands are not launches ​

profiles and the mcp servers are subcommands, not launches, so launch-only arguments do not apply to them — the positional [PROFILE], --cwd, --mode, and a trailing -- <provider args> are all rejected with a clear error rather than silently dropped:

sh
hyprpilot engineer profiles     # error: positional <PROFILE> does not apply to `profiles`
hyprpilot --cwd /tmp profiles   # error: --cwd does not apply to `profiles`

The one exception is --with-config: profiles honors it (the overlay preview above), while the mcp servers — which read none of the launch config — reject it too. Run the launch and the subcommand as separate invocations.

Exit behavior ​

Because a successful launch replaces the process, hyprpilot's own exit code is the vendor CLI's on unix (non-unix platforms fall back to spawn-and-propagate-exit-code). Config load failures, an empty profiles list, an unresolvable profile, or a missing system_prompt file abort before exec with a readable error naming the problem.