Matrix logo

Daemon

The daemon entry point wires configuration, engine, and transport layers. It supports three modes: HTTP API server, MCP stdio server, and selftest.

Source file: cmd/tachyond/main.go

The daemon entry point wires configuration, engine, and transport layers. It supports three modes: HTTP API server, MCP stdio server, and selftest.


Design decisions

Flag-based mode selection

Three mutually exclusive modes, selected by flags:

./bin/tachyond              # HTTP API server (default)
./bin/tachyond --mcp        # MCP stdio server
./bin/tachyond --selftest   # MCP tool registry selftest, then exit

The --mcp flag redirects logs to stderr so stdout is reserved for NDJSON-RPC. The --selftest flag verifies tool registry consistency and exits with code 0 or 1.

Signal handling

The HTTP server runs in a goroutine; the main thread blocks on signal.Notify for SIGINT/SIGTERM. On signal, it initiates a graceful shutdown with a 10-second timeout.

sig := make(chan os.Signal, 1)
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
<-sig

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
srv.Shutdown(ctx)

Fatal error handling

Config load failures and engine init failures are fatal (os.Exit(1)). Server failures in the HTTP goroutine are also fatal. Crashing on misconfiguration is preferred over limping with undefined behavior.

No daemonization

The daemon does not fork, write PID files, or implement systemd notify. It is designed to run under a process supervisor (systemd, Docker, etc.) that handles these concerns.


Startup flow

Parse flags (--mcp, --selftest)
    │
    ▼
Configure logger (stdout for HTTP, stderr for MCP/selftest)
    │
    ▼
Selftest? → verify tool registry → exit 0/1
    │
    ▼
Load config (tachyon.config.kvx + environment + .env)
    │
    ▼
Initialize engine (registry, chains, compiler, tester, simulator, deployer, wallet gate)
    │
    ▼
MCP mode? → RunStdio(eng) → block on stdin
    │
    ▼
HTTP mode? → api.New(eng, logger) → ListenAndServe → block on signal

Thin CLI client

The cmd/tachyon/ binary is a thin HTTP client, not the daemon itself. It reads JSON from stdin and posts to the daemon's REST endpoints:

echo '{"project_root":"."}' | tachyon compile
tachyon health
tachyon chains

The CLI defaults to http://127.0.0.1:8645 (overridable via --addr or TACHYON_HTTP_ADDR). Request timeout is 30 minutes for POST (long builds/tests), 120 seconds for GET.


Modifying the daemon

What to changeWhere
Add flagcmd/tachyond/main.go - flag declarations
Add startup modecmd/tachyond/main.go - switch after flag parse
Change shutdown timeoutcmd/tachyond/main.go - context.WithTimeout
Add health checkpkg/api/server.go - handleHealthz