The daemon subsystem manages background codefly processes -- long-running services, the Mind Gateway, and agent health monitoring.
┌──────────────────────────────────────────────────┐
│ codefly daemon │
│ │
│ ┌────────────┐ ┌───────────┐ ┌─────────────┐ │
│ │ Start │ │ Monitor │ │ Gateway │ │
│ │ │ │ │ │ │ │
│ │ Re-exec │ │ CPU/Mem │ │ Mind gRPC │ │
│ │ + detach │ │ tracking │ │ server │ │
│ └────────────┘ └───────────┘ └─────────────┘ │
│ │
│ State: ~/.codefly/daemon.pid │
│ Logs: ~/.codefly/daemon.log │
└──────────────────────────────────────────────────┘
Starts a detached background process. By default, it runs codefly run service with any flags passed after --.
codefly daemon start
codefly daemon start -- --runtime-context nix
codefly daemon start -- -d --service-path ./my-svcGateway mode: Start the Mind Gateway gRPC server instead of running services.
codefly daemon start --gateway
codefly daemon start --gateway --dir /path/to/workspace --port 50051| Flag | Default | Description |
|---|---|---|
--gateway |
false | Start Mind Gateway instead of services |
--dir |
. |
Working directory (gateway mode only) |
--port |
50051 | gRPC listen port (gateway mode only) |
Sends SIGTERM to the daemon process and waits up to 10 seconds for graceful shutdown. Falls back to SIGKILL if the process doesn't exit.
codefly daemon stopStops the running daemon (if any), then starts a new one.
codefly daemon restart
codefly daemon restart -- --runtime-context dockerChecks if the daemon is running and prints PID and log path.
codefly daemon status
# Daemon is running (PID 12345)
# Logs: /Users/you/.codefly/daemon.logDisplays daemon log output.
codefly daemon logs # Print all logs
codefly daemon logs -f # Follow log output (like tail -f)
codefly daemon logs -n 50 # Show last 50 lines| Flag | Description |
|---|---|
-f, --follow |
Follow log output continuously |
-n, --tail |
Show last N lines |
Checks all codefly-related processes for resource issues.
codefly daemon monitor # One-shot check
codefly daemon monitor -w # Continuous monitoring (every 30s)
codefly daemon monitor --kill-orphans # Kill orphaned agent processes| Flag | Description |
|---|---|
-w, --watch |
Run continuously (check every 30s) |
--kill-orphans |
Kill orphaned go-grpc/go-generic agent processes |
Runs the Mind Gateway gRPC server in the foreground. This is typically invoked by daemon start --gateway, not directly.
codefly daemon gateway --dir /workspace --port 50051- Check if a daemon is already running (read PID file, signal 0)
- If already running, return error with existing PID
- Open/truncate the log file (
~/.codefly/daemon.log) - Find the current executable path
- Re-exec the binary with the target command (e.g.,
run service) - Set
SysProcAttr.Setsid = trueto detach from the terminal session - Redirect stdout/stderr to the log file, close stdin
- Start the child process
- Write the child PID to
~/.codefly/daemon.pid - Release the child process (prevent zombie)
- Read PID from
~/.codefly/daemon.pid - Check if the process is alive (signal 0)
- Send SIGTERM for graceful shutdown
- Poll every 200ms for up to 10 seconds
- If still alive after 10s, send SIGKILL
- Remove the PID file
The daemon uses signal 0 (proc.Signal(syscall.Signal(0))) to check if a process is alive without affecting it. This handles stale PID files from crashed processes.
All state files live in ~/.codefly/:
| File | Purpose |
|---|---|
daemon.pid |
PID of the running daemon process |
daemon.log |
stdout/stderr output from the daemon |
monitor.log |
Output from the process monitor |
The state directory is created automatically (0755 permissions) on first use.
The monitor scans for codefly-related processes using ps aux and checks against patterns: go-grpc, go-generic, codefly, neo4j, mind-server.
| Check | Default | Action |
|---|---|---|
| CPU > 200% | Warning | Auto-kill agent processes |
| CPU > 100% for 2 consecutive checks | Kill | Kill agent processes (30s interval) |
| Memory > 512MB | Warning | Log warning |
| Orphaned agents > 3 | Warning | Log warning |
When running with --watch, the monitor:
- Checks processes every 30 seconds
- Tracks consecutive high-CPU PIDs across checks
- Kills agent processes (go-grpc, go-generic) that exceed the threshold for 2+ consecutive checks
- Logs all warnings and periodic status to
~/.codefly/monitor.log - Cleans up tracking state when processes die
Only agent processes (go-grpc, go-generic) are auto-killed. The main codefly process and infrastructure services (neo4j) are never automatically killed.
Codefly Process Monitor -- 14:23:45
Total: 5 processes, 45.2% CPU, 256MB memory
PID CPU% MEM(MB) PROCESS
12345 12.3 64 go-grpc
12346 8.5 128 codefly
12347 24.4 64 go-generic
Warnings:
HIGH MEM: PID 12346 (codefly) at 640MB
The gateway mode starts a Mind Gateway gRPC server as a daemon. This is used by the Mind engineering platform to communicate with the local codefly workspace.
codefly daemon start --gateway --dir /path/to/workspace --port 50051The gateway:
- Listens on the specified gRPC port (default 50051)
- Writes a port file for service discovery
- Cleans up the port file on exit
- Responds to SIGINT for graceful shutdown
Every Gateway method is classified as an effect or an observation, once, in
pkg/gateway/effect. The classification is enforced for every request by a
unary and a stream interceptor installed where the server is registered, so it
is not something a method has to remember.
- A request carrying no Work Context capability is served exactly as before. Ordinary Gateway use is unaffected.
- A request carrying a capability is a governed request. A governed
effect — anything that writes the workspace, runs code, moves repository
history, touches a forge or drives a live process — is refused with
Unimplemented, before its handler runs. The gateway holds none of the four live sources core's verifier requires (the authorization revision, the replay store, the grant source, the seal source), so it cannot turn a presented capability into a verified one and will not admit an unverified one. - A governed observation is served. It records nothing either way, so refusing it would deny reads to a governed caller and protect nothing.
- A method the classification does not name is refused outright. A new RPC
declares what it does before it serves anything;
pkg/gateway/effect's inventory test walks the generated service descriptor, so this surfaces at test time rather than in production.
The container executor (pkg/gateway/dockerexec) is a second implementation of
the same contract and is reached without an interceptor, so it calls the same
boundary from its effect methods.
This replaces a per-call-site gate. Previously three methods — ApplyEdit,
ApplySymbolPatch and Test — asked whether the request was governed, and the
other fifty-four performed the effect with the capability in the metadata
ignored. --governed-execution arms the receipt journal, its attestor and
recovery; it does not make a governed effect servable. That becomes possible
when the component holding those four sources verifies the capability and hands
the recorder a verified one.