Troubleshooting
Most kutl problems are diagnosable from a single command: kutl status. It runs from anywhere, works whether the daemon is up or not, and (with --format json) produces a stable machine-readable dump suitable for pasting into support issues.
Reading kutl status
A healthy run looks roughly like this:
daemon: running (PID 12345, $KUTL_HOME=~/.kutl)
identity: local (no relay token yet)
did: did:key:z6Mk...
name: Alice
spaces (2 registered):
✓ my-project /home/alice/code/proj relay=ws://127.0.0.1:9100/ws last-activity=12s ago signals=0
✗ old-test /home/alice/scratch <path missing>
relays:
ws://127.0.0.1:9100/ws reachableEach section answers one question: is the daemon up, who am I, which spaces are registered (and are their paths still there), and can this machine reach the relays they point at.
Common situations
daemon: not running
Sync only happens while the daemon is running. Start it with kutl daemon start. If it exits immediately, check ~/.kutl/logs/daemon.log for the failure reason.
relay unreachable
Either the relay is down or this machine cannot reach it. Verify the URL with curl against the relay's HTTP equivalent. If the relay requires authentication, also check identity: in the status output.
space marked ✗
The reason prints in angle brackets: path missing (the registered directory is gone), config unreadable (its .kutl/space.toml cannot be read), or relay unreachable (the space is fine but its relay is not answering). If you moved the directory, run kutl init in the new location. It re-registers a folder that already has its space config. Entries whose .kutl/space.toml no longer exists are pruned automatically the next time the registry is written.
relay refused the connection
Client and relay must agree on the major version of the sync protocol. A relay that has moved to a newer major refuses an older kutl at the handshake and says which side is behind:
relay refused the connection: relay requires protocol version 3 or later (this client speaks 2); upgrade kutlUpgrade the client and reconnect; nothing on disk needs to change:
brew upgrade kutlThe mirror case, a kutl newer than its relay, is stopped on the client side instead, with a different message and without the prefix above:
relay speaks protocol version 1, this client requires 2; upgrade the relayThen the relay is the side to upgrade; see Self-Hosting a Relay.
Capturing a debug bundle
To send detailed state to support:
kutl status --format json > kutl-status.json
# also include the daemon log if applicable
cp ~/.kutl/logs/daemon.log .Verbose daemon logs
Restart the daemon with KUTL_LOG=debug to capture detailed sync activity:
kutl daemon stop
KUTL_LOG=debug kutl daemon start
# reproduce the issue, then tail the per-space log
# (the space id comes from `kutl status --format json`)
tail -f ~/.kutl/logs/<space-id>.logEach space logs to its own file at ~/.kutl/logs/<space-id>.log; daemon.log holds the supervisor's lifecycle output.