Exit Codes

Every failure hypha itself reports is classifiable from the process exit status alone — no need to parse error text. Success envelopes exit 0; failures carry a stable code in the envelope and a typed exit status:

CodeMeaning
0Success
1Argument parsing failed before hypha ran — unknown subcommand, unknown flag, missing required argument. See below.
2User error (bad args, malformed path, non-loopback bind)
3Not found (symbol/package absent across plan → store → Hackage)
4Network error (offline cache miss, HTTP 429/503, transport failure)
5Cache / on-disk corruption
7Environment error (no plan.json, unreachable store)
8Tool missing — a required external binary (haddock, cabal, ghc) is not on $PATH
9Internal error — an exception escaped hypha's own error handling. A bug; the envelope carries INTERNAL_ERROR.

1 versus 2

1 comes from the argument parser, before any command runs, and so is the one code with no envelope on stdout — the usage message goes to stderr instead. 2 is hypha's own validation of an argument it did parse:

$ hypha nosuchcommand      # unknown subcommand      -> 1, usage on stderr
$ hypha --nosuchflag       # unknown flag            -> 1, usage on stderr
$ hypha package            # missing required arg    -> 1, usage on stderr
$ hypha symbol not-a-path  # malformed identifier    -> 2, error envelope

An agent that branches on the envelope should treat 1 as "I called hypha wrong" and re-read --help, not as a failure of the query.

If you are seeing 8 (TOOL_MISSING) unexpectedly, you are probably running under a sandbox that hides the toolchain — see Troubleshooting.