v0.1.0 — under verification, no public release yet

A maintained distribution
around OpenCode

Isolated configuration, an approval-gated policy, a Hu Tao agent and theme, cross-platform lifecycle tools, and a ZITADEL-protected control plane — without forking OpenCode's agent loop.

The departed leave no instructions.
Only the living can choose what comes next.

What it adds

Everything OpenCode already does well, it keeps doing. The harness wraps it in a hardened, isolated, lifecycle-managed shell.

Hu Tao Primary Agent

A production-minded persona — finish the job, never fabricate, verify with real output. Ships with a wine-and-parchment terminal theme.

Approval-Gated Policy

Shell, edits, grep, and external-directory access require approval. Destructive commands and secret-path reads are denied. Fail-closed enforcement via checksummed inline config.

Cross-Platform Lifecycle

Atomic install, update, rollback, and uninstall on Linux, macOS, and Windows. Versioned releases with pointer-based activation and per-install locking.

ZITADEL Control Plane

Administrator-only BFF with OIDC Authorization Code + PKCE. Server-side sessions with ID rotation. Allowlisted, schema-validated upstream responses. CSRF-protected mutations.

Metadata Audit Plugin

JSONL audit records of session lifecycle and tool execution — no prompts, no file content. Optional journald duplication outside service-user control.

Isolated Namespaces

Config, state, data, cache, and audit logs live under ~/.hutao. A normal OpenCode installation is left untouched. Override every path with environment variables.

Install

From a trusted local checkout for now. Versioned release installation will be available once Forgejo and signing are set up.

# Verify the 14-file installer payload $ python3 scripts/verify_release_manifest.py # Install from a local checkout $ HUTAO_SOURCE_DIR="$PWD" sh ./install.sh # Check health $ hutao doctor # Launch $ hutao
# Verify the 14-file installer payload PS> python scripts/verify_release_manifest.py # Install from a local checkout PS> $env:HUTAO_SOURCE_DIR = (Get-Location).Path PS> .\install.ps1 # Check health PS> hutao doctor # Launch PS> hutao

The installer pins OpenCode 1.18.4 and verifies its SHA-256 digest. It stages and validates all 14 payload files before activation, atomically advances the current pointer, and preserves previous for rollback.

Architecture

The browser never touches OpenCode directly. Caddy terminates TLS; the BFF and OpenCode bind to loopback only.

Browser ──→ Caddy / TLS ──→ Hu Tao Control Plane (127.0.0.1:8898) ──→ OpenCode Server (127.0.0.1:4096) ↳ OIDC: ZITADEL · Authorization Code + PKCE · confidential client ↳ Sessions: server-side, ID rotation, no refresh-on-read ↳ BFF output: allowlisted, schema-validated, no prompts or credentials ↳ Loopback-only: OpenCode Basic auth, no external exposure

The hutao shim reads the marked HUTAO_HOME, resolves the current pointer to a versioned release, exports the checksummed enforced-policy.json through OPENCODE_CONFIG_CONTENT, and invokes the pinned OpenCode binary by absolute path.

Security model

Defense in depth — not a sandbox. Every layer fails closed.

§Sharing disabled by default. OpenCode's share feature is off.
§Secret paths denied. .env, .env.*, credential files — blocked at read. .env.example remains readable.
§Destructive commands denied. rm -rf, mkfs, dd if=, volume deletion, hard Git reset, and more.
§Loopback-only binding. OpenCode and the BFF bind to 127.0.0.1. Caddy is the sole public endpoint.
§OIDC with PKCE. ZITADEL discovery, JWKS validation, confidential client, project-qualified roles, exact organization binding, administrator role required.
§Session ID rotation. Login rotates the server-side session ID. Read requests don't refresh sessions — a logged-out session stays logged out.
§Schema-validated BFF output. Non-scalar upstream values are rejected, not silently dropped. Prompts, provider metadata, MCP commands, and model options never reach the browser.
§CSRF on all mutations. Session abort is the only exposed mutation. IDs are restricted, upstream 404/409 preserved.
§Audit without content. Metadata-only JSONL records. Production lines also emitted to journald — service users can't truncate the journal.
§Fail-closed policy. If the checksummed enforced-policy.json is missing, the launcher refuses to start.

Isolation

Every namespace is separate. A normal OpenCode installation is untouched.

ItemDefault path
Harness home~/.hutao
Active release~/.hutao/current
OpenCode config~/.hutao/current/config
Config namespace~/.hutao/xdg-config
State namespace~/.hutao/xdg-state
Data~/.hutao/data
Cache~/.hutao/cache
Audit log~/.hutao/state/audit.jsonl
Versioned runtimes~/.hutao/releases/<release>/runtime
Config backups~/.hutao/backups

Override with HUTAO_HOME, HUTAO_CONFIG_HOME, HUTAO_STATE_HOME, HUTAO_DATA_HOME, HUTAO_CACHE_HOME, HUTAO_AUDIT_LOG.

Lifecycle

No network self-updater. Updates require a locally verified installer with a trusted SHA-256.

$ hutao doctor # health check $ hutao version # print harness + OpenCode version $ hutao rollback # swap current ↔ previous $ hutao uninstall # remove runtime + launcher, keep data $ hutao uninstall --purge # delete the entire harness root # Secure update with a trusted installer $ HUTAO_INSTALLER_PATH=/path/to/install.sh \ HUTAO_INSTALLER_SHA256=<trusted-sha256> \ hutao update