Process model¶
Kukeon ships a single binary. Both kuke and kukeond are the same compiled file, dispatched by name at process start.
argv[0] dispatch¶
From cmd/main.go:
exe := filepath.Base(os.Args[0])
switch exe {
case "kuke": runKuke()
case "kukeond": runKukeond()
default:
// Optional fallback
debug := os.Getenv("KUKEON_DEBUG_MODE")
if debug == "kuke" || debug == "kukeond" { ... }
fmt.Fprintf(os.Stderr, "unknown entry command: %s\n", exe)
os.Exit(1)
}
- If you call
kuke, you get the client CLI. - If you call
kukeond, you get the daemon. - If you call the binary by any other name (for example from an IDE or debugger where the executable is named something like
__debug_bin12345), it errors out unlessKUKEON_DEBUG_MODE=kukeorKUKEON_DEBUG_MODE=kukeondis set.
There is no kuke kukeond subcommand. Running kuke kukeond … is an error; the dispatch happens before cobra sees any arguments.
Why not two binaries?¶
- The CLI and the daemon share most of their code (the controller, the apischeme conversion, the error types). Shipping one binary means shipping half the bytes and testing one build.
- Installers only need to copy one file; the hard link is a one-liner.
- The CLI can fall back to "be the daemon for one command" — in-process mode, reached via an explicit
--run-pathorKUKEON_NO_DAEMON=true— without duplicating any logic.
The daemon process¶
kukeond is a standard long-lived Go program. It:
- Parses flags (
--run-path,--containerd-socket,--socket,--log-level). - Writes a pid file at
<run-path>/kukeond.pid. - Opens the unix socket at
--socket(default/run/kukeon/kukeond.sock). - Starts serving the
kukeonv1API. - On SIGINT/SIGTERM: closes the listener, drains in-flight requests, removes the pid file, exits.
The daemon does not fork or daemonize itself. When you run kuke init, the daemon is started inside a containerd-managed container (as the root container of the kukeond cell in the system realm), not by kuke forking a background process. See System realm.
The client process¶
Every kuke invocation is a short-lived process:
- Parse flags, load config.
- If promoted to in-process mode (explicit
--run-path,KUKEON_NO_DAEMON=true, or--no-daemonon one of the commands that still ship it —init,uninstall,purge, everyget <kind>), run the operation in-process. - Otherwise, dial the daemon socket, send one
kukeonv1request, print the response, exit.
Clients do not hold persistent connections. Each command opens a new socket, sends, receives, closes. There's no keepalive or session state.
Signals¶
kukeond— SIGINT and SIGTERM trigger a clean shutdown. SIGKILL skips shutdown (and leaves the pid file behind; clean it up by hand).kuke— SIGINT cancels the current request. The client sends a cancellation through the RPC; the daemon aborts the operation on a best-effort basis.
Exit codes¶
0— success.1— any failure. Kukeon does not currently differentiate exit codes beyond that; see the structured error log for details.