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 change | Where |
|---|---|
| Add flag | cmd/tachyond/main.go - flag declarations |
| Add startup mode | cmd/tachyond/main.go - switch after flag parse |
| Change shutdown timeout | cmd/tachyond/main.go - context.WithTimeout |
| Add health check | pkg/api/server.go - handleHealthz |
