The non-interactive CLI for scripts and AI agents. All output is JSON.
kd start runs a daemon in the foreground. The daemon holds the connection, the mount, and the session state.
Every other command is a one-shot client. It connects to the daemon over a Unix socket, sends one request, prints one line of JSON, and exits.
The socket path is $KD_SOCKET, or /tmp/kd.sock by default. One daemon per socket. To run two daemons on one machine, see How to run two instances.
Source: cmd/kd/main.go.
Every command prints exactly one JSON object:
{"ok":true,"data":{...}}
{"ok":false,"error":"...","code":"..."}
On failure, code is a stable classification of the message in error. Branch on code, never on the message text. New codes may be added, and existing ones do not change.
When the daemon is not running, the client prints the error to stderr instead:
{"ok":false,"error":"daemon not running (socket: /tmp/kd.sock)","code":"not_connected"}
The exit code carries the same classification as code, so a script can branch on $? without parsing the JSON. Only success exits 0.
| Exit | code | Meaning |
|---|---|---|
| 0 | ok | Success. |
| 1 | internal | An error the daemon did not classify, or a response the client could not read. |
| 2 | not_connected | No session, or the client cannot reach the daemon socket. |
| 3 | timeout | A command with a timeout did not finish in time. |
| 4 | not_found | The file or target does not exist. |
| 5 | invalid_argument | A missing or malformed argument. |
| 6 | busy | Already running, or already mounted. |
| 7 | refused | Fingerprint mismatch, or the listener is closed. |
| 8 | unsupported | Unknown command, or unknown target for kd show. |
kd pull missing-file.txt
# prints {"ok":false,"error":"file not found: missing-file.txt","code":"not_found"}
# exit code is 4
if kd pull report.pdf ./report.pdf >/dev/null; then echo "pulled"; fi
# jq is not needed to detect a failure
These numbers are a stable contract, covered by a test. Source: cmd/kd/agent.go.
| Command | Description |
|---|---|
kd start | Start the daemon in the foreground. Configure with environment variables before this call. Ctrl-C stops it cleanly. |
kd stop | Disconnect, unmount, and shut the daemon down. kd quit is an alias. |
kd version | Show version and commit hash. |
kd help | Show the built-in help. --help and -h are aliases. |
| Command | Description |
|---|---|
kd show [what] | Show info: fingerprint, ip, peer, relay, status, config, or all. |
kd invite [origin] | This peer's code as links a person can open. Send invite_link: a page with the download and the code on it. web_link opens the browser peer, app_link opens an installed app. Give an origin to point invite_link at a page of your own. |
kd register <fingerprint> | Register the peer's fingerprint, or any link kd invite produces. In LAN mode (KD_LOCAL set) the daemon has no code: kd show fingerprint answers with local_address, and kd register wants that ip:port address and refuses an 86-character code with "invalid address format". |
kd connect | Connect to the registered peer. The role is chosen automatically: the lower fingerprint creates the room, the higher one joins. |
kd create | Create a room and wait for the peer. Use when you control the roles yourself. |
kd join | Join a room the peer created first. |
kd discover | Scan the local network. Returns your session name and the peers found: {"my_name":"...","peers":[{"name":"...","addr":"..."}]}. The first call takes about 6 seconds. |
kd connect-lan <peer-name> <peer-addr> | Connect to a peer found by discover, with the role chosen automatically. |
kd disconnect | Disconnect and reset the session. Returns a new fingerprint. Saved contacts still reconnect. |
kd status | Connection status and session info. See Status fields. |
kd peer-info | Peer details and connection mode. |
| Command | Description |
|---|---|
kd add <filepath> | Share a file or directory with the peer. |
kd add-as <path> <remote-name> | Share with a custom remote name. |
kd unshare <filename> | Stop sharing a file. The file stays on disk. |
kd list | List all shared files, local and remote. |
kd pull <name> [local-path] | Download a remote file. Without local-path it lands in the save path. |
kd cancel-download <name> | Pause an active download. Partial data is kept. Run kd pull again to resume. |
kd progress <name> | Download progress, 0-100. |
kd file-size <name> | Get a remote file's size. |
kd local-file-path <name> | Get the real local path of a file. |
kd bench-pull <name> [path] | Pull a file, report MB/s, then delete the local copy. |
| Command | Description |
|---|---|
kd contacts | List saved contacts with online status. |
kd add-contact <name> <fingerprint> | Save a contact. |
kd remove-contact <fingerprint> | Remove a saved contact. |
kd quick-connect <fingerprint> | Connect to a saved contact. No new fingerprint exchange. |
kd save-contact <name> | Save the currently connected peer as a contact. |
| Command | Description |
|---|---|
kd incognito [on|off] | Query or toggle incognito mode. Incognito uses ephemeral keys and writes nothing to disk. Interrupted downloads do not resume across a disconnect in this mode. |
kd poll-event | Pop the next event from the event queue. See Events. |
kd export-logs [dest] | Export a sanitized copy of the log. sanitize-logs is an alias. |
kd config-path | Show the config file path. |
kd log-path | Show the log file path. |
kd poll-event is non-blocking. It returns {"event":""} when the queue is empty. The queue holds 64 events. On overflow, the oldest event is dropped. Poll faster than events arrive.
Events the daemon emits:
| Event | Meaning |
|---|---|
connect_status:Waiting for peer... | Room created, waiting for the peer. |
connect_status:peer_not_ready | Join attempted before the peer created the room. |
connect_status:Waiting for peer to connect... | Handshake in progress. |
connection_mode:lan / direct / bridge / direct-out / direct-in | Connected; which network path is in use. direct-out: this side's reads go directly to the peer and only the return leg rides the relay. direct-in: the peer's reads arrive directly and this side's go through the relay. Also emitted when a reconnect changes the path. |
peer_disconnected:health_timeout | The peer stopped answering heartbeats. |
reconnecting: | Automatic reconnection started. |
reconnected: | Reconnection succeeded. Shared files are restored, partial downloads resume. |
resuming_downloads:<N> | N interrupted downloads resume automatically. |
gave_up: | Reconnection stopped after repeated failures. |
mount_gone: | The mounted folder went away under a live session (an eject, a driver restart). The daemon remounts it; the peer's session is not touched. |
mount_back: | The folder answers again after a mount_gone:. |
mount_failed:<reason> | Three mount attempts in a row failed. The daemon keeps trying once a minute; received files still land in the save folder. |
relay_busy:<text> | The relay reports its free lane under load. At most once per ten minutes, never on a paid lane. |
relay_slow:<text> | A read on the free relay lane waited more than two seconds for one fetch. Once per session, never on a paid lane or a direct link. |
disk_low:<free MB> | The save folder's disk dropped under the floor (64 MB: two read-ahead blocks plus a margin). Reads that need bytes from the peer fail with ENOSPC, the read-ahead window and prefetch stop, until space is freed. Once per crossing. |
disk_ok: | The save folder's disk has space again after a disk_low:. |
kd status returns these fields:
| Field | Values |
|---|---|
running | true / false |
connection_status | healthy, degraded, disconnected, unknown |
connection_mode | lan, direct, bridge, direct-out, direct-in. The two mixed values appear when one side sits behind a blocked inbound and the other is reachable: the reachable side's leg stays direct and only the other leg rides the relay, so relay credit is spent on that leg alone. |
state | idle, waiting_for_peer, connected, reconnecting, gave_up, mount_gone, mount_failed. One value for scripts; the same words the desktop app and the kdmcp kd_status tool show. |
state_text | The state as a sentence, for example Connected via relay, paid lane or nas is away, reconnecting (attempt 2 of 10). |
mount_ready | true when the FUSE folder is mounted and served. false while the mount is being restored or with FUSE off. |
throttled | true when a read on the free relay lane waited seconds for one fetch this session. Always false on a paid lane or a direct link. state_text then ends in shared right now. |
disk_low | true while the save folder's disk is under the free-space floor. state_text then ends in save disk almost full. |
throughput | recv_bps and sent_bps over the last second. |
reconnect | Present while reconnecting: attempt and max_attempts. |
fingerprint, peer_fingerprint | Your identity and the peer's. |
ip, peer_ip, ipv4, peer_ipv4 | Advertised addresses. The IPv4 ones are what the relay saw each side on; a peer that offers no IPv6 route is dialed there. |
relay, fuse, mount_path, save_path | Session configuration in effect. |
local_files, remote_files | Counts of shared files on each side. |
writer_epoch | Internal session counter. |
Set these before kd start. They have no effect on client commands.
| Variable | Default | Meaning |
|---|---|---|
KD_RELAY | https://keibidroprelay.keibisoft.com/ | Relay URL. |
KD_INBOUND_PORT | 26441 | Listen port. Must be in 26000-27000. The desktop app uses 26431. |
KD_OUTBOUND_PORT | 26442 | Outbound port. Must be in 26000-27000. The desktop app uses 26432. |
KD_SAVE_PATH | ~/KeibiDrop/Received | Where received files are saved. |
KD_MOUNT_PATH | ~/KeibiDrop/Mount | FUSE mount point. |
KD_NO_FUSE | false | Disable the FUSE mount. |
KD_LOG_FILE | per platform | Log file path. See Files and folders. |
KD_INCOGNITO | false | Ephemeral keys, nothing written to disk. |
KD_PASSPHRASE_PROTECT | false | Ask for a passphrase to encrypt the identity. |
KD_SOCKET | /tmp/kd.sock | Daemon socket path. |
KD_LOCAL | unset | Any non-empty value starts the daemon in LAN mode. |
KEIBIDROP_CONFIG_DIR | ~/.config/keibidrop | Move the whole config directory. Use for a second instance. |
Boolean values: 0, false, no, and off mean false. Any other non-empty value means true. KD_NO_FUSE=false keeps FUSE on.
The full option list, config file keys, and precedence rules are in the configuration reference.