Command reference
This reference omits the retired agent instruction-management commands (hack setup sync, standalone hack setup exports and hack agent prime), which refuse in v5. See Agent integrations for the opt-in plugin and MCP setup.
Run hack help <command> for the same content in the terminal. Global options: --no-interactive (or HACK_NO_INTERACTIVE=1); JSON shapes vary by command and backend. See Command and output contracts for envelopes, bare reports and streamed records.
Project
hack project
Inspect or manage project metadata
Usage
hack project <subcommand> [options]Subcommands
| Command | Summary |
|---|---|
hack project owner | Inspect project ownership |
hack project target | Inspect the exact project, checkout, instance and service a command would target (read-only, provisional) |
hack project task | Discover reviewed task recipes without running them (read-only, provisional) |
Options
| Option | Description |
|---|---|
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack project owner
Inspect project ownership
Usage
hack project owner <subcommand> [options]Subcommands
| Command | Summary |
|---|---|
hack project owner show | Show the local ownership metadata for the current project |
Options
| Option | Description |
|---|---|
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack project target
Inspect the exact project, checkout, instance and service a command would target (read-only, provisional)
Usage
hack project target [options]Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
--branch <name> | Run against a branch-specific instance (compose name + hostnames) |
--service <service> | Also resolve one Compose service of the target |
| `--env <name | base |
--expect-generation <id> | Refuse unless the project's config generation still equals this id |
--json | Output JSON (machine-readable) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack project task
Discover reviewed task recipes without running them (read-only, provisional)
Usage
hack project task <subcommand> [options]Subcommands
| Command | Summary |
|---|---|
hack project task list | List reviewed task recipes and refusals for the target (read-only, provisional; runs nothing) |
hack project task inspect <task> | Show one reviewed task recipe: argv, service, env scope, effects and pins (read-only, provisional; runs nothing) |
Options
| Option | Description |
|---|---|
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack init
Initialize a repo (generate .hack/ with compose + config)
Usage
hack init [options]Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--manual | Skip discovery and define services manually (or generate a minimal compose in --auto) |
--auto | Run non-interactive init with sensible defaults |
--name <slug> | Project slug (default: repo name) |
--dev-host <host> | DEV_HOST override (new projects use global default_domain, or hack.local) |
--oauth | Enable OAuth-safe alias host |
--oauth-tld <tld> | OAuth alias TLD override (default: gy) |
--no-discovery | Skip discovery and generate a minimal compose |
| `--with <claude | codex>` |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack up [services...]
Start project services (docker compose up)
Usage
hack up [services...] [options]Arguments
| Arg | Description |
|---|---|
services |
Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
| `--env <name | base |
--branch <name> | Run against a branch-specific instance (compose name + hostnames) |
--detach, -d | Run in background (docker compose up -d) |
--profile <name[,name...]> | Enable one or more compose profiles (comma-separated) |
| `--target <auto | local |
--json | Output JSON (machine-readable) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack down
Stop project services (docker compose down)
Usage
hack down [options]Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
| `--env <name | base |
--branch <name> | Run against a branch-specific instance (compose name + hostnames) |
--profile <name[,name...]> | Enable one or more compose profiles (comma-separated) |
| `--target <auto | local |
--prune-caches | After down, remove confirmed Compose-owned disposable cache volumes |
--remove-data | Native backend: delete a stopped project's owned data volumes so the next up starts fresh (asks first) |
--yes | Confirm --prune-caches or --remove-data without prompting |
--json | Output JSON (machine-readable) |
--recover | Explicitly reconcile an interrupted native stop, or stop the services of a native run whose foreground owner exited, while retaining data |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack restart [services...]
Restart the project or selected services
Usage
hack restart [services...] [options]Arguments
| Arg | Description |
|---|---|
services |
Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
| `--env <name | base |
--branch <name> | Run against a branch-specific instance (compose name + hostnames) |
--profile <name[,name...]> | Enable one or more compose profiles (comma-separated) |
| `--target <auto | local |
--json | Output JSON (machine-readable) |
--recover-frontend | Recover an interrupted native frontend after proving its owner and effects are gone |
--expect-finalization-attempt <32-hex> | Require this exact interrupted native frontend attempt |
--expect-frontend-pid <pid> | Previously observed frontend PID (required only for legacy v1 state) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack ps
Show project status (docker compose ps)
Usage
hack ps [options]Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
--branch <name> | Run against a branch-specific instance (compose name + hostnames) |
--profile <name[,name...]> | Enable one or more compose profiles (comma-separated) |
--json | Output JSON (machine-readable) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack tui
Open the project TUI (services + logs)
Usage
hack tui [options]Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack run <service> [cmd...]
Run a one-off command in a service container (docker compose run --rm)
Usage
hack run [options] <service> [cmd...]Everything from <cmd> on is passed to the command unchanged, including flags such as --version or --help. Put Hack options before it; a leading -- is optional.
Arguments
| Arg | Description |
|---|---|
service | |
cmd |
Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
| `--env <name | base |
--branch <name> | Run against a branch-specific instance (compose name + hostnames) |
--workdir <path> | Working directory inside the container (docker compose run -w) |
--profile <name[,name...]> | Enable one or more compose profiles (comma-separated) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack exec <service> [cmd...]
Run a command in an already-running service container (docker compose exec)
Usage
hack exec [options] <service> [cmd...]Everything from <cmd> on is passed to the command unchanged, including flags such as --version or --help. Put Hack options before it; a leading -- is optional.
Arguments
| Arg | Description |
|---|---|
service | |
cmd |
Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
| `--env <name | base |
--branch <name> | Run against a branch-specific instance (compose name + hostnames) |
--workdir <path> | Working directory inside the container (docker compose run -w) |
--profile <name[,name...]> | Enable one or more compose profiles (comma-separated) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack logs [service]
Tail logs (compose by default; Loki for queries/history via --loki/--query)
Usage
hack logs [service] [options]Arguments
| Arg | Description |
|---|---|
service |
Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
--branch <name> | Run against a branch-specific instance (compose name + hostnames) |
--follow, -f | Follow logs (default for hack logs) |
--no-follow | Print logs and exit (do not follow) |
--tail <n> | Tail last N log lines (default: 200) |
--pretty | Pretty-print logs (best-effort JSON parsing + formatting) |
--json | Output JSON (machine-readable) |
--profile <name[,name...]> | Enable one or more compose profiles (comma-separated) |
--compose | Read logs directly from docker compose (bypass Loki) |
--loki | Force Loki backend (do not fall back to docker compose logs) |
--services <csv> | Filter Loki logs by service(s), comma-separated (e.g. api,www) |
--query <logql> | Raw LogQL selector/query (overrides auto selector built from project + services) |
--since <time> | Start time for Loki logs (RFC3339 or duration like 15m) |
--until <time> | End time for Loki logs (RFC3339 or duration like 15m) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack open [target]
Open a project URL (OAuth alias by default when enabled; otherwise dev host)
Usage
hack open [target] [options]Arguments
| Arg | Description |
|---|---|
target |
Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
--branch <name> | Run against a branch-specific instance (compose name + hostnames) |
| `--prefer <auto | alias |
--json | Output JSON (machine-readable) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack branch
Manage branch aliases for a project
Usage
hack branch <subcommand> [options]Subcommands
| Command | Summary |
|---|---|
hack branch add <name> | Register a branch alias for this project |
hack branch list | List registered branch aliases for this project |
hack branch remove <name> | Remove a branch alias for this project |
hack branch open <name> | Open the branch host in a browser |
Options
| Option | Description |
|---|---|
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack branch add <name>
Register a branch alias for this project
Usage
hack branch add <name> [options]Arguments
| Arg | Description |
|---|---|
name |
Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
--note <text> | Optional note for the branch entry |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack branch list
List registered branch aliases for this project
Usage
hack branch list [options]Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack branch remove <name>
Remove a branch alias for this project
Usage
hack branch remove <name> [options]Arguments
| Arg | Description |
|---|---|
name |
Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack branch open <name>
Open the branch host in a browser
Usage
hack branch open <name> [options]Arguments
| Arg | Description |
|---|---|
name |
Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
| `--prefer <auto | alias |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack config
Read/write legacy config or validate native project configuration
Usage
hack config <subcommand> [options]Subcommands
| Command | Summary |
|---|---|
hack config get <key> | Read a value from hack.config.json |
hack config set <key> <value> | Update a value in hack.config.json |
hack config validate | Validate native configuration and selected local overlays without starting workloads |
hack config plan | Inspect native environment binding completeness without decrypting or starting workloads |
hack config import | Preview a bounded legacy config and Compose conversion without writes |
hack config adopt | Explicitly adopt a stopped, verified existing Compose instance |
Options
| Option | Description |
|---|---|
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack config get <key>
Read a value from hack.config.json
Usage
hack config get <key> [options]Arguments
| Arg | Description |
|---|---|
key |
Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
--global | Read/write global ~/.hack/hack.config.json |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack config set <key> <value>
Update a value in hack.config.json
Usage
hack config set <key> <value> [options]Arguments
| Arg | Description |
|---|---|
key | |
value |
Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
--global | Read/write global ~/.hack/hack.config.json |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack config validate
Validate native configuration and selected local overlays without starting workloads
Usage
hack config validate [options]Uses the matching bundled Rust compiler. Without --file, discovers a native project and resolves permitted worktree-local overlay and routing settings. --file validates only the explicit document. With HACK_RUNTIME_BACKEND=native, a selected workload image that is not a sha256: content ID refuses with the native consumer's native_graph_admission code. Neither mode reads env values, writes state, or starts workloads.
Options
| Option | Description |
|---|---|
--file <path> | Validate only this native project JSON file, without discovery or local overrides |
--profile <names> | Comma-separated declared native profiles |
--domain <suffix> | Select the generated native routing domain suffix |
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
| `--env <name | base |
--json | Output JSON (machine-readable) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack config plan
Inspect native environment binding completeness without decrypting or starting workloads
Usage
hack config plan [options]Resolves the native project, permitted local env selection and routing preview, then inspects managed-env names, winning scopes and secret flags. Managed YAML is parsed by its existing owner; keys and values are never decrypted or returned. Required unresolved refs return a nonzero exit. This experimental report does not establish runtime admission or enable native execution; use config validate for validation without managed-document reads.
Options
| Option | Description |
|---|---|
--profile <names> | Comma-separated declared native profiles |
--domain <suffix> | Select the generated native routing domain suffix |
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
| `--env <name | base |
--json | Output JSON (machine-readable) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack config import
Preview a bounded legacy config and Compose conversion without writes
Usage
hack config import [options]Requires --dry-run. Inspects the exact .hack/hack.config.json and docker-compose.yml pair, reports field mappings/refusals, and validates complete private candidates in memory. Does not export a draft, adopt resources, read keys or change project selection.
Options
| Option | Description |
|---|---|
--dry-run | Preview only; adoption and draft export are unavailable |
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--json | Output JSON (machine-readable) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack config adopt
Explicitly adopt a stopped, verified existing Compose instance
Usage
hack config adopt [options]Qualifies a strict static legacy subset with exact existing data volumes. --dry-run reports fields without writes. Adoption journals the stopped format switch and holds original files for rollback; retained-container commands never create replacement data. Requires an upgraded launcher and the Compose backend, also for --dry-run; on another backend, rerun with HACK_RUNTIME_BACKEND=compose. Verified linked Git checkouts retain explicit existing identities. Local inheritance, generated overrides and container recreation remain unsupported.
Options
| Option | Description |
|---|---|
--stop | Explicitly journal and stop the exact original containers before adopting; never removes data anchors |
--dry-run | Read-only field, compiler and existing-resource preview |
--rollback | Restore the exact held legacy inputs after the original containers are stopped |
--recover | Explicitly repair interrupted adoption or rollback using the saved original binding |
--branch <value> | Select the exact existing branch instance |
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--json | Output JSON (machine-readable) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack session
Manage persistent project workspaces with tmux-first onboarding
Usage
hack session <subcommand> [options]Sessions keep a project workspace alive across terminal restarts, SSH reconnects, and long-running agent work. The guided default is tmux, including hack setup tmux for a popup picker. Other mux backends such as zellij still exist through sessions.mux, but the interactive session tooling is tmux-first today.
Subcommands
| Command | Summary |
|---|---|
hack session list | List active workspaces |
hack session start [project] | Reuse the default project workspace or create an isolated one |
hack session stop <workspace> | Stop a workspace |
hack session attach <workspace> | Attach to an existing workspace |
hack session exec <workspace> <command> | Send a command to a running workspace |
hack session panes <workspace> | List panes in a tmux workspace |
hack session capture <workspace> | Capture recent output from a tmux workspace |
hack session tail <workspace> | Tail output from a tmux workspace |
Options
| Option | Description |
|---|---|
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack session list
List active workspaces
Usage
hack session list [options]Options
| Option | Description |
|---|---|
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack session start [project]
Reuse the default project workspace or create an isolated one
Usage
hack session start [project] [options]Reuse the default project workspace when it already exists, or create an isolated long-running workspace with --new or --name. Use --detach when another tool should keep the workspace alive without attaching your terminal.
Arguments
| Arg | Description |
|---|---|
project | Project name or path |
Options
| Option | Description |
|---|---|
--up | Run hack up -d before creating or attaching |
--new | Create an isolated workspace instead of reusing the default project workspace |
--name <value> | Suffix for an isolated workspace name (for example: agent-1 -> project--agent-1) |
--detach, -d | Create or reuse the workspace without attaching (for GUI/non-TTY use) |
| `--env <name | base |
| `--service <global | service>` |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack session stop <workspace>
Stop a workspace
Usage
hack session stop <workspace> [options]Arguments
| Arg | Description |
|---|---|
workspace | Workspace name |
Options
| Option | Description |
|---|---|
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack session attach <workspace>
Attach to an existing workspace
Usage
hack session attach <workspace> [options]Attach to a running workspace by name. Tmux switches clients instead of nesting tmux inside tmux, while zellij attaches to the named session directly.
Arguments
| Arg | Description |
|---|---|
workspace | Workspace name |
Options
| Option | Description |
|---|---|
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack session exec <workspace> <command>
Send a command to a running workspace
Usage
hack session exec [options] <workspace> <command><command> is one argument: quote a command that has its own arguments or flags, as in "npm --version". Put Hack options before it; a leading -- is optional.
Queue a command in the workspace without opening a new interactive attach flow. Tmux sends it to the active pane; zellij opens a new pane for the command. This is useful for long-running agents, background checks, or remote follow-up work.
Arguments
| Arg | Description |
|---|---|
workspace | Workspace name |
command | Command to execute in workspace |
Options
| Option | Description |
|---|---|
| `--env <name | base |
| `--service <global | service>` |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack session panes <workspace>
List panes in a tmux workspace
Usage
hack session panes <workspace> [options]Arguments
| Arg | Description |
|---|---|
workspace | Workspace name |
Options
| Option | Description |
|---|---|
--json | Output JSON (machine-readable) |
--pretty | Pretty-print logs (best-effort JSON parsing + formatting) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack session capture <workspace>
Capture recent output from a tmux workspace
Usage
hack session capture <workspace> [options]Arguments
| Arg | Description |
|---|---|
workspace | Workspace name |
Options
| Option | Description |
|---|---|
--target <target> | Tmux pane target (default: active pane) |
--lines <n> | Number of lines to capture (default: 200) |
--json | Output JSON (machine-readable) |
--pretty | Pretty-print logs (best-effort JSON parsing + formatting) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack session tail <workspace>
Tail output from a tmux workspace
Usage
hack session tail <workspace> [options]Arguments
| Arg | Description |
|---|---|
workspace | Workspace name |
Options
| Option | Description |
|---|---|
--target <target> | Tmux pane target (default: active pane) |
--lines <n> | Number of lines to capture (default: 200) |
--interval-ms <ms> | Polling interval in milliseconds (default: 500) |
--max-ms <ms> | Stop tailing after N milliseconds (default: 5000) |
--json | Output JSON (machine-readable) |
--pretty | Pretty-print logs (best-effort JSON parsing + formatting) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
Global infrastructure
hack global
Manage machine-wide infra (DNS/TLS, Caddy proxy, logs)
Usage
hack global <subcommand> [options]Subcommands
| Command | Summary |
|---|---|
hack global install | Bootstrap ~/.hack and start Caddy + Grafana/Loki/Alloy |
hack global dns | Manage scoped native custom-domain DNS |
hack global up | Start global infra containers |
hack global down | Stop global infra containers |
hack global status | Show status for global infra (containers + networks) |
hack global logs [service] | Tail global infra logs (caddy|grafana|loki|alloy) |
hack global ca | Export Caddy Local CA cert (print path or PEM) |
hack global cert <hosts...> | Generate local TLS certs via mkcert (for non-Caddy services) |
hack global trust | Trust Caddy Local CA (macOS) so https://*.hack is trusted |
hack global logs-reset | Wipe Loki, Grafana and Alloy volumes (fresh logs, dashboards and Alloy read positions) |
hack global authorize | Authorize passwordless DNS recovery commands on macOS |
Options
| Option | Description |
|---|---|
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack global install
Bootstrap ~/.hack and start Caddy + Grafana/Loki/Alloy
Usage
hack global install [options]Options
| Option | Description |
|---|---|
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack global dns
Manage scoped native custom-domain DNS
Usage
hack global dns <subcommand> [options]Subcommands
| Command | Summary |
|---|---|
hack global dns preview | Preview a scoped native custom-domain DNS claim or the hack.local relay repair without changing the host |
hack global dns activate | Activate only the selected native custom-domain DNS suffix |
hack global dns deactivate | Remove an owned native custom-domain DNS suffix, or undo the hack.local relay repair |
Options
| Option | Description |
|---|---|
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack global up
Start global infra containers
Usage
hack global up [options]Options
| Option | Description |
|---|---|
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack global down
Stop global infra containers
Usage
hack global down [options]Options
| Option | Description |
|---|---|
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack global status
Show status for global infra (containers + networks)
Usage
hack global status [options]Options
| Option | Description |
|---|---|
--json | Output JSON (machine-readable) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack global logs [service]
Tail global infra logs (caddy|grafana|loki|alloy)
Usage
hack global logs [service] [options]Arguments
| Arg | Description |
|---|---|
service |
Options
| Option | Description |
|---|---|
--follow, -f | Follow logs (default for hack logs) |
--no-follow | Print logs and exit (do not follow) |
--tail <n> | Tail last N log lines (default: 200) |
--pretty | Pretty-print logs (best-effort JSON parsing + formatting) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack global ca
Export Caddy Local CA cert (print path or PEM)
Usage
hack global ca [options]Options
| Option | Description |
|---|---|
--print | Print the CA cert PEM to stdout (instead of printing its path) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack global cert <hosts...>
Generate local TLS certs via mkcert (for non-Caddy services)
Usage
hack global cert <hosts...> [options]Uses mkcert to generate a cert/key pair under ~/.hack/certs (or --out).
Arguments
| Arg | Description |
|---|---|
hosts |
Options
| Option | Description |
|---|---|
--install | Run mkcert -install before generating certs |
--out <dir> | Directory for generated cert/key (default: ~/.hack/certs) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack global trust
Trust Caddy Local CA (macOS) so https://*.hack is trusted
Usage
hack global trust [options]Options
| Option | Description |
|---|---|
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack global logs-reset
Wipe Loki, Grafana and Alloy volumes (fresh logs, dashboards and Alloy read positions)
Usage
hack global logs-reset [options]Options
| Option | Description |
|---|---|
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack global authorize
Authorize passwordless DNS recovery commands on macOS
Usage
hack global authorize [options]Options
| Option | Description |
|---|---|
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack status
Show project status (shortcut for hack projects --details)
Usage
hack status [options]Options
| Option | Description |
|---|---|
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
--include-global | Include global infra projects under ~/.hack (e.g. logging stack) |
--all | Include unregistered docker compose projects (best-effort) |
--meta | Include git/worktree/session/env metadata (implies --details) |
--json | Output JSON (machine-readable) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack usage
Show resource usage across running projects
Usage
hack usage [options]Options
| Option | Description |
|---|---|
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
--details | Show per-container usage and mount types |
--include-global | Include global infra projects under ~/.hack (e.g. logging stack) |
--watch | Refresh usage continuously |
--interval <value> | Refresh interval (ms) for --watch |
--no-host | Skip host process metrics |
--json | Output JSON (machine-readable) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack projects
Show all projects (registry + running docker compose)
Usage
hack projects <subcommand> [options]Subcommands
| Command | Summary |
|---|---|
hack projects prune | Remove stale registry entries and stop orphaned containers |
Options
| Option | Description |
|---|---|
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
--details | Show per-project service tables |
--summary | Return compact project counts with --json; load details with --project |
--timings | Write numeric listing phase timings to stderr (requires --json) |
--no-daemon | Read runtime directly instead of the daemon cache |
--meta | Include git/worktree/session/env metadata (implies --details) |
--include-global | Include global infra projects under ~/.hack (e.g. logging stack) |
--all | Include unregistered docker compose projects (best-effort) |
--json | Output JSON (machine-readable) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack projects prune
Remove stale registry entries and stop orphaned containers
Usage
hack projects prune [options]Options
| Option | Description |
|---|---|
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
--include-global | Include global infra projects under ~/.hack (e.g. logging stack) |
--dry-run | Report prune candidates without changing registry entries or containers |
--json | Output JSON (machine-readable) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
Diagnostics
hack log-pipe
Read log lines from stdin and pretty-print them (best-effort JSON parsing)
Usage
hack log-pipe [options]Options
| Option | Description |
|---|---|
| `--format <auto | docker-compose |
| `--stream <stdout | stderr>` |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack doctor
Validate local setup for the selected runtime, routing, trust and project
Usage
hack doctor [options]Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--fix | Attempt safe auto-remediations (network + CoreDNS + CA) |
--migrate-env-config | Migrate legacy hack.env.json/.env state to the new env config files |
--accept-tracked-env-changes | With --migrate-env-config and no prompt, allow deleting or editing git-tracked files (hack.env.json, the Compose file) |
| `--domain-migration preview | apply |
--json | Output JSON (machine-readable) |
--browser-url https://app.hack | HTTPS origin manually tested in the browser (no path or credentials) |
| `--browser-result unknown | works |
--branch <name> | Run against a branch-specific instance (compose name + hostnames) |
--native-cleanup inspect | Inspect one mapped native graph's pending cleanup without recovery or stop replay |
| `--native-run-mapping inspect | repair |
--expect-selection <64-hex> | Require the exact run-mapping recovery inspection selection |
--accept-legacy-device-rebind | Explicitly accept legacy migration without proof of original filesystem volume continuity |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack crash-capture
Capture OrbStack/system/docker diagnostics into .tmp for post-failure triage
Usage
hack crash-capture [options]Collects structured snapshots after a runtime failure: hack status/logs, docker state, OrbStack process details, and filtered macOS unified logs.
Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--since <duration> | Look-back window for system logs (for example: 30m, 2h) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack daemon
Manage the local hack daemon (hackd)
Usage
hack daemon <subcommand> [options]Subcommands
| Command | Summary |
|---|---|
hack daemon start | Start hackd (local daemon) |
hack daemon stop | Stop hackd |
hack daemon restart | Restart hackd |
hack daemon status | Show hackd status |
hack daemon metrics | Show hackd metrics |
hack daemon logs | Show hackd logs |
hack daemon clear | Clear stale hackd pid/socket files |
hack daemon install | Install hackd as a launchd service (macOS) |
hack daemon uninstall | Uninstall hackd launchd service (macOS) |
Options
| Option | Description |
|---|---|
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack daemon start
Start hackd (local daemon)
Usage
hack daemon start [options]Options
| Option | Description |
|---|---|
--foreground | Run hackd in the foreground (debug) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack daemon stop
Stop hackd
Usage
hack daemon stop [options]Options
| Option | Description |
|---|---|
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack daemon restart
Restart hackd
Usage
hack daemon restart [options]Options
| Option | Description |
|---|---|
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack daemon status
Show hackd status
Usage
hack daemon status [options]Options
| Option | Description |
|---|---|
--json | Output JSON (machine-readable) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack daemon metrics
Show hackd metrics
Usage
hack daemon metrics [options]Options
| Option | Description |
|---|---|
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack daemon logs
Show hackd logs
Usage
hack daemon logs [options]Options
| Option | Description |
|---|---|
--tail <n> | Tail last N log lines (default: 200) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack daemon clear
Clear stale hackd pid/socket files
Usage
hack daemon clear [options]Options
| Option | Description |
|---|---|
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack daemon install
Install hackd as a launchd service (macOS)
Usage
hack daemon install [options]Options
| Option | Description |
|---|---|
--run-at-load | Start hackd automatically on login |
--no-run-at-load | Do not start hackd automatically on login |
--gui-only | Only run in GUI sessions (default) |
--no-gui-only | Run in all session types (including SSH) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack daemon uninstall
Uninstall hackd launchd service (macOS)
Usage
hack daemon uninstall [options]Options
| Option | Description |
|---|---|
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack update
Update hack to the latest release
Usage
hack update [options]Downloads and installs the latest stable hack release from GitHub.
Notes:
- Refuses to self-update when running from a Homebrew install, local dev wrapper, or symlink install.
- Updates the current hack binary and refreshes assets.
Options
| Option | Description |
|---|---|
--check | Check for updates (do not install) |
--yes | Apply update without prompting |
--tag <tag> | Update to a specific release tag (e.g. v1.4.0) |
--json | Output JSON (machine-readable) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack version
Print version
Usage
hack version [options]Options
| Option | Description |
|---|---|
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack help [path...]
Show help for a command (e.g. hack help global logs)
Usage
hack help [path...] [options]Arguments
| Arg | Description |
|---|---|
path |
Options
| Option | Description |
|---|---|
--all | Include experimental (unsupported) commands in help output |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
Agents
hack mcp
Manage MCP server integrations for coding agents
Usage
hack mcp <subcommand> [options]Subcommands
| Command | Summary |
|---|---|
hack mcp serve | Run the MCP server over stdio |
hack mcp print | Print MCP config snippets |
Options
| Option | Description |
|---|---|
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack mcp serve
Run the MCP server over stdio
Usage
hack mcp serve [options]Options
| Option | Description |
|---|---|
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack mcp print
Print MCP config snippets
Usage
hack mcp print [options]Options
| Option | Description |
|---|---|
--bundle <directory> | Select a verified candidate MCP bundle (requires --cli) |
--cli <executable> | Pin the Hack executable used by candidate MCP tools |
--runtime-directory <directory> | Select a private candidate MCP socket directory |
| `--scope <user | project>` |
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--all | Target all supported clients |
--cursor | Target Cursor MCP config |
--claude | Target Claude CLI MCP config |
--codex | Target Codex MCP config |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack setup
Explicit opt-in skills and MCP; legacy automation is retired
Usage
hack setup <subcommand> [options]Subcommands
| Command | Summary |
|---|---|
hack setup tmux | Install the recommended tmux binding for hack workspaces |
hack setup migrate | Migrate standalone skills to the hack plugin; preserve Cursor rules |
Options
| Option | Description |
|---|---|
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack setup tmux
Install the recommended tmux binding for hack workspaces
Usage
hack setup tmux [options]Options
| Option | Description |
|---|---|
--check | Check whether integration is installed |
--remove | Remove integration files/config |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack setup migrate
Migrate standalone skills to the hack plugin; preserve Cursor rules
Usage
hack setup migrate [options]Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--global | Migrate user-scope files under HOME instead of the project |
--all-scopes | Migrate both project and user-scope files |
--claude | Limit to Claude Code files (default: all clients) |
--codex | Limit to Codex files (default: all clients) |
--cursor | Limit to Cursor files (default: all clients) |
--skip-plugin-check <clients> | Treat the plugin as verified for these comma-separated clients (claude, codex, cursor, or all) after checking it loads yourself |
--apply | Remove the previewed Hack-owned standalone files after backing them up (default: read-only preview) |
--rollback-manifest <manifest> | Restore the exact files recorded in a migration backup manifest |
--json | Output JSON (machine-readable) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack agent
Agent utilities
Usage
hack agent <subcommand> [options]Subcommands
| Command | Summary |
|---|---|
hack agent patterns | Print agent init patterns guide |
hack agent init | Print agent init prompt |
hack agent onboard | Print the project onboarding prompt (agent-assisted setup) |
Options
| Option | Description |
|---|---|
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack agent patterns
Print agent init patterns guide
Usage
hack agent patterns [options]Options
| Option | Description |
|---|---|
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack agent init
Print agent init prompt
Usage
hack agent init [options]Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
| `--client, -c <cursor | claude |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack agent onboard
Print the project onboarding prompt (agent-assisted setup)
Usage
hack agent onboard [options]Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
Secrets & env
hack secrets
Manage secrets in OS keychain (Bun.secrets)
Usage
hack secrets <subcommand> [options]Subcommands
| Command | Summary |
|---|---|
hack secrets set [name] | Store a secret |
hack secrets get [name] | Print a secret (exit 1 if missing) |
hack secrets delete [name] | Delete a stored secret |
Options
| Option | Description |
|---|---|
--service <service> | Override Bun.secrets service name (default: hack-cli) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack secrets set [name]
Store a secret
Usage
hack secrets set [name] [options]Arguments
| Arg | Description |
|---|---|
name |
Options
| Option | Description |
|---|---|
--service <service> | Override Bun.secrets service name (default: hack-cli) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack secrets get [name]
Print a secret (exit 1 if missing)
Usage
hack secrets get [name] [options]Arguments
| Arg | Description |
|---|---|
name |
Options
| Option | Description |
|---|---|
--service <service> | Override Bun.secrets service name (default: hack-cli) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack secrets delete [name]
Delete a stored secret
Usage
hack secrets delete [name] [options]Asks for confirmation before deleting. Without a TTY (or with HACK_NO_INTERACTIVE / --no-interactive) the deletion is refused with E_INTERACTIVE_REQUIRED unless --yes is passed.
Arguments
| Arg | Description |
|---|---|
name |
Options
| Option | Description |
|---|---|
--service <service> | Override Bun.secrets service name (default: hack-cli) |
--yes | Confirm the deletion without prompting (required without a TTY or with HACK_NO_INTERACTIVE) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
Integrations
hack env
Set project env vars and local secrets
Usage
hack env <subcommand> [options]Subcommands
| Command | Summary |
|---|---|
hack env list | List resolved env values for the selected overlay |
hack env get <key> | Print one resolved env value without an added newline |
hack env explain <key> | Explain a resolved env value without revealing it |
hack env apply | Recreate one service with its resolved env |
hack env add [key] [value] | Add or update an env value |
hack env set [key] [value] | Alias for env add |
hack env hydrate | Import many values into the machine-local env layer at once |
hack env materialize | Write a compatibility .env file from the selected overlay |
hack env exec [command...] | Run a host command with project env injected |
hack env shell | Open a host shell with project env injected |
hack env unset [key] | Remove an env value from the canonical config |
hack env backend | Manage env/secret storage backend strategy |
Options
| Option | Description |
|---|---|
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack env list
List resolved env values for the selected overlay
Usage
hack env list [options]Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
| `--env <name | base |
--json | Output JSON (machine-readable) |
--show-secrets | Print secret values (keychain) in plaintext |
| `--service <global | service>` |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack env get <key>
Print one resolved env value without an added newline
Usage
hack env get <key> [options]Read one global or service value without starting a runtime. Empty values succeed; missing values fail. Omit --env to use the configured default, or use --env default for base layers. Plaintext is written only to stdout; errors go to stderr.
Arguments
| Arg | Description |
|---|---|
key |
Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
| `--env <name | base |
| `--service <global | service>` |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack env explain <key>
Explain a resolved env value without revealing it
Usage
hack env explain <key> [options]Arguments
| Arg | Description |
|---|---|
key |
Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
| `--env <name | base |
--json | Output JSON (machine-readable) |
| `--service <global | service>` |
| `--target <host | compose>` |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack env apply
Recreate one service with its resolved env
Usage
hack env apply [options]Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
| `--env <name | base |
--json | Output JSON (machine-readable) |
| `--service <global | service>` |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack env add [key] [value]
Add or update an env value
Usage
hack env add [key] [value] [options]Non-secret values may be passed as arguments. For secrets, pipe the value with --value-stdin (for example <secret-source> \| hack env add API_TOKEN --secret --value-stdin) or omit the value in a terminal to use the hidden prompt, so the value never appears in argv, shell history, or process listings.
Arguments
| Arg | Description |
|---|---|
key | |
value |
Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
| `--env <name | base |
--secret | Store value as an encrypted secure entry |
--value-stdin | Read the value from piped stdin (max 64 KiB, one trailing newline stripped) so it never appears in argv or shell history |
--local | Write to the worktree-local env override file instead of the shared repo env file |
| `--service <global | service>` |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack env set [key] [value]
Alias for env add
Usage
hack env set [key] [value] [options]Same value rules as hack env add: pipe secrets with --value-stdin or use the hidden prompt instead of passing them as arguments.
Arguments
| Arg | Description |
|---|---|
key | |
value |
Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
| `--env <name | base |
--secret | Store value as an encrypted secure entry |
--value-stdin | Read the value from piped stdin (max 64 KiB, one trailing newline stripped) so it never appears in argv or shell history |
--local | Write to the worktree-local env override file instead of the shared repo env file |
| `--service <global | service>` |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack env hydrate
Import many values into the machine-local env layer at once
Usage
hack env hydrate [options]Reads KEY=value entries from piped stdin or --file (never from arguments) and writes them, in one atomic commit, to the worktree-local env file (hack.env.local.yaml, or hack.env.<overlay>.local.yaml with --env). Tracked env files are never written. Repeating an import with the same values changes nothing; other local entries are kept. Values are never printed.
Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
| `--env <name | base |
--json | Output JSON (machine-readable) |
--secret | Store value as an encrypted secure entry |
| `--service <global | service>` |
--file <path> | Read entries from this file (or a pipe such as <(producer)) instead of stdin |
| `--format <env | json>` |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack env materialize
Write a compatibility .env file from the selected overlay
Usage
hack env materialize [options]Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
| `--env <name | base |
| `--service <global | service>` |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack env exec [command...]
Run a host command with project env injected
Usage
hack env exec [options] [command...]Everything from <command> on is passed to the command unchanged, including flags such as --version or --help. Put Hack options before it; a leading -- is optional.
Inject the selected Hack env overlay directly into a one-off host command without materializing .hack/.env. To inspect a value, prefer printenv KEY or sh -lc 'printf "%s\n" "$KEY"'; echo $KEY expands in your current shell before Hack injects env.
Arguments
| Arg | Description |
|---|---|
command |
Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
| `--env <name | base |
| `--service <global | service>` |
| `--target <host | compose>` |
--shell <command> | Run a shell command string via /bin/sh -lc after env injection so $VAR expansion happens inside the child shell |
--timeout <seconds> | Bound a non-TTY host command; terminate its process group and return 124 on expiry |
| `--lifetime <command | persistent>` |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack env shell
Open a host shell with project env injected
Usage
hack env shell [options]Start an interactive host shell with the selected Hack env overlay injected into the process environment.
Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
| `--env <name | base |
| `--service <global | service>` |
| `--target <host | compose>` |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack env unset [key]
Remove an env value from the canonical config
Usage
hack env unset [key] [options]Arguments
| Arg | Description |
|---|---|
key |
Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
| `--env <name | base |
--local | Write to the worktree-local env override file instead of the shared repo env file |
| `--service <global | service>` |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack env backend
Manage env/secret storage backend strategy
Usage
hack env backend <subcommand> [options]Subcommands
| Command | Summary |
|---|---|
hack env backend status | Show configured env/secret backend strategy |
hack env backend use <backend> | Select env/secret backend strategy |
Options
| Option | Description |
|---|---|
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack host
Run host-side commands with project env injected
Usage
hack host <subcommand> [options]Use hack host when a command should run on your host machine, not inside the compose network, but still needs Hack-resolved env and host-local rewrites.
Subcommands
| Command | Summary |
|---|---|
hack host ps | Inspect host command lifetimes, CPU and lifecycle ownership (read-only) |
hack host exec [command...] | Run a host command with project env injected |
hack host shell | Open a host shell with project env injected |
Options
| Option | Description |
|---|---|
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack host ps
Inspect host command lifetimes, CPU and lifecycle ownership (read-only)
Usage
hack host ps [options]Options
| Option | Description |
|---|---|
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
--json | Output JSON (machine-readable) |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack host exec [command...]
Run a host command with project env injected
Usage
hack host exec [options] [command...]Everything from <command> on is passed to the command unchanged, including flags such as --version or --help. Put Hack options before it; a leading -- is optional.
Run a one-off command on the host with the selected Hack env overlay injected. Use --scope when you want service-scoped values without running inside that service container. To inspect a value, prefer printenv KEY or sh -lc 'printf "%s\n" "$KEY"'; echo $KEY expands in your current shell before Hack injects env.
Arguments
| Arg | Description |
|---|---|
command |
Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
| `--env <name | base |
| `--scope <global | service>` |
| `--target <host | compose>` |
--shell <command> | Run a shell command string via /bin/sh -lc after env injection so $VAR expansion happens inside the child shell |
--timeout <seconds> | Bound a non-TTY host command; terminate its process group and return 124 on expiry |
| `--lifetime <command | persistent>` |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
hack host shell
Open a host shell with project env injected
Usage
hack host shell [options]Start an interactive host shell with the selected Hack env overlay injected. Use --scope when you want service-scoped values without running inside that service container.
Options
| Option | Description |
|---|---|
--path, -p <dir> | Run a project command against a repo path (overrides cwd search) |
--project <name> | Target a registered project by name (from ~/.hack/projects.json) |
| `--env <name | base |
| `--scope <global | service>` |
| `--target <host | compose>` |
--no-interactive | Never prompt: apply documented defaults or fail with E_INTERACTIVE_REQUIRED (also via HACK_NO_INTERACTIVE=1) |
--help, -h | Show help |
--version, -v | Show version |
Source: v5 (next.12) · docs/reference/cli.md.