Background
Spec §5 at `docs/superpowers/specs/2026-04-21-no-proxy-mode-design.md` allocates:
| code |
meaning |
| 5 |
mode-conflict (`ErrModeConflict`) |
| 6 |
not-initialized (`ErrNoMarker` reached by a command that requires the app to exist on the server) |
Currently every error returned from a cobra RunE surfaces as exit code 1. `ErrModeConflict` is `%w`-wrapped through `formatModeConflictError` and `errors.Is(err, ErrModeConflict)` already works in-process — it just isn't plumbed to `os.Exit`.
Proposal
Plumb the exit code via the `cmd/cmdutil` entry point. Options:
- Inspect the final error via `errors.Is` at the top-level `rootCmd.Execute()` wrapper and call `os.Exit(5)` or `os.Exit(6)` accordingly.
- Add a typed error wrapper carrying the desired exit code and have `cmdutil` unwrap it.
Option 2 scales if more codes are added (it also lets us distinguish 4 = validation from 2 = usage).
Acceptance
- `conoha app deploy --no-proxy ` against a proxy-marker app exits 5.
- `conoha app logs ` against an unmarked server exits 6.
- Existing exit 1 behavior preserved for generic errors.
- Integration test in `cmd/app/` asserts the top-level `os.Exit` code.
Pointer
- `cmd/cmdutil` — top-level Execute wrapper
- `cmd/app/mode.go` — `ErrModeConflict`, `ErrNoMarker`
- Spec §5 and plan Self-Review note at `docs/superpowers/plans/2026-04-21-no-proxy-mode.md`
Deferred during PR #103.
Background
Spec §5 at `docs/superpowers/specs/2026-04-21-no-proxy-mode-design.md` allocates:
Currently every error returned from a cobra RunE surfaces as exit code 1. `ErrModeConflict` is `%w`-wrapped through `formatModeConflictError` and `errors.Is(err, ErrModeConflict)` already works in-process — it just isn't plumbed to `os.Exit`.
Proposal
Plumb the exit code via the `cmd/cmdutil` entry point. Options:
Option 2 scales if more codes are added (it also lets us distinguish 4 = validation from 2 = usage).
Acceptance
Pointer
Deferred during PR #103.