Headless

Headless Help Documentation

Headless mode lets Hawa Code run without launching the terminal interactive interface, making it suitable for UI-less environments, remote services, and automation scenarios. Note that Headless is NOT enabled via a --headless parameter. Hawa Code provides two UI-less ways of running:

  1. hcode server: Headless resident service. The process stays running without rendering a terminal UI, with a built-in WebServer (HTTP + WebSocket) for remote control via browser. This is the official Headless run mode.
  2. hcode -p "...": Single-turn non-interactive mode. Executes one task, prints the result to standard output, and exits. Suitable for pipes and script invocation, but not a resident service.

Note: The headlessBrowser setting (headless browser) is used for web page fetching and rendering, and is unrelated to the Headless run mode. Do not confuse the two.


1. Differences Between the Two Modes

Comparison hcode server hcode -p "..."
Run mode Process stays resident, does not exit Exits after a single run
Interactivity Real-time interaction in browser, tool-call approval No interaction, one-shot output
Use cases Remote resident services, UI-less environments CI/CD, scripts, pipe invocation
  • Use hcode server when you need to “run long-term on a remote machine and use the full Agent capability via browser”.
  • Use hcode -p when you need to “run a single command in a pipeline and judge the result by exit code”.

2. Starting the Headless Service with hcode server

2.1 Command Format

hcode server [options]

2.2 Parameters

Parameter Description
--port <n> Web service port. Reads settings.webServer.port by default, falling back to 3210; automatically increments by 1 on port conflict
--host <addr> Bind address, defaults to 127.0.0.1. Binding to a non-loopback address (e.g., 0.0.0.0) requires --token, otherwise startup fails
--token <token> Access token. Passed via WebSocket subprotocol or ?token= query param for WS handshake; via Authorization: Bearer <token> for REST
--resume <id> Resume a historical session (matching the full log path or file name suffix <id>.jsonl); exits with code 1 if not found
--cwd <path> Working directory, defaults to the process’s current directory
--verbose Verbose output
--dangerously-skip-permissions Skip all permission confirmations; carries security risks, see Notes

Command-line parameters take precedence over the webServer configuration in settings.json; in Headless mode, webServer.enabled is forcibly treated as enabled.

2.3 Examples

hcode server                                    # Local 127.0.0.1:3210, open in browser
hcode server --port 4000 # Specify a port
hcode server --host 0.0.0.0 --token mytok # Expose externally (token required)
hcode server --resume 2026-11-06T... # Resume a historical session

3. Prerequisites

  1. Complete terminal-mode initialization first: Headless mode skips terminal-interaction-dependent steps such as Onboarding, the trust dialog, and MCP approval. Please run hcode once in terminal mode first to complete initialization configuration such as model/API.
  2. Model and API configuration: Make sure the model and API have been configured via terminal mode and are valid; startup or queries will report errors if the configuration is invalid.
  3. Permissions and token: Binding to a loopback address (e.g., 127.0.0.1) requires no token; binding to a non-loopback address requires --token, otherwise the service fails to start.
  4. Working directory: The process automatically grants read permission to the --cwd directory, without terminal trust confirmation.

4. How to Tell If Startup Succeeded

Signs of a successful startup:

  1. Hawa Code headless server starting... and Tools, commands and MCP clients loaded, starting Web server... appear on standard output in sequence.
  2. Followed by Hawa Code headless server started and the access URL (e.g., URL: http://127.0.0.1:3210); if a token is configured, access instructions are also printed. The actual port is subject to the URL: line in the startup output (already incremented by 1 on port conflict).
  3. The process stays resident and does not exit; open the URL in a browser to use it.

After a session starts, session content is no longer printed to terminal standard output; session messages are persisted as JSONL and pushed to the browser in real time via WebSocket.


5. Logs and Troubleshooting

Logs are located under UCODE_ROOT_DIR/projects/<project directory>/:

Path Content
messages/*.jsonl Session message records
log/*.log Runtime logs
log/error-<date>.log Error logs
errors/*.txt Error records
mcp-logs-<server>/ Logs of each MCP Server

Common failure signals and exit codes:

Symptom Description
Failed to start WebServer: ... and exits with code 1 WebServer failed to start, commonly due to non-loopback binding without token, port occupied, etc.
Session log not found: <id> and exits with code 1 The session log specified by --resume does not exist
Process killed or exits after successful startup Abnormal; check the error logs

Suggested troubleshooting order: check the hints in standard output → inspect log/error-*.log → check whether the browser connection is rejected due to token → check MCP logs if necessary.


6. CI/CD and Script Scenarios

  • Prefer hcode -p: Executes one query, prints the result to standard output, and exits with code 0, suitable as a CI step judged by exit code.

    hcode -p "Fix the lint errors"
    echo "instruction" | hcode -p # Standard input is also supported

    The process exits with code 1 when standard input has no content.

  • Use hcode server for resident remote services / UI-less environments: runs resident on servers, Docker, systemd, with the browser as the frontend.

  • Batch and automation tasks: Tasks can be submitted programmatically via the WebServer REST / WebSocket API (REST requires a Bearer token).


7. Notes

  1. Permission confirmations require someone to approve in the browser: In Headless mode, the Web client is the only approval channel; tool confirmations time out after about 5 minutes if no client responds.
  2. Security risks of --dangerously-skip-permissions: This parameter skips all permission confirmations, and the Headless path does not perform the isolated-environment check from terminal mode. Use it only in trusted, isolated environments.
  3. Mind standard input when running in the background: Running in the background via systemd, docker run -d, etc. is unaffected; but pipe/heredoc scenarios (e.g., somecmd | hcode server) block startup while waiting for stdin EOF. When running in the background, make sure standard input is /dev/null or set CI=true.
  4. Port conflicts are handled automatically: On port occupation, the port is incremented by 1 automatically; the actual port is subject to the URL: line in the startup output.
  5. Token security: The token appears in process arguments and the URL query param; on multi-user machines, beware of leaks via process listings and browser history.
  6. Other limitations: No built-in task timeout or failure retry; the integrity of cross-session recovery via --resume has not been fully validated; the Headless path does not execute SessionStart hooks — users relying on that hook to inject context should take note.