WebSocket protocol

A single JSON protocol powers file tree, editor, terminal, git, and chat. The UI never assumes it runs on the same machine as the server.

Full spec on GitHub →

Message framing

Three message kinds, each one JSON object per text frame:

Requests (client → server)

{ "id": 1, "command": "read_file", "args": { "path": "/home/user/a.txt" } }

Replies (server → client)

{ "id": 1, "ok": true,  "result": { ... } }
{ "id": 1, "ok": false, "error": "File already exists" }
Commands run concurrently and replies may arrive out of order — match them by id. A malformed frame gets error: "invalid request: …"; an unknown command gets error: "unknown command: …".

Events (server → client)

EventPayloadNotes
pty-outputsession_id, dataRaw terminal bytes, ANSI escapes intact.
pty-exitsession_id, codecode is null when unknown.
chat-stream-chunkid, stream, textOne line per chunk from the agent CLI.
chat-stream-doneid, error?Terminates a chat stream.

Command reference

Terminal (PTY)

CommandArgsResult
pty_spawnsessionId, shell?, cwd?, cols?, rows?{ id, pid }
pty_writesessionId, datanull
pty_resizesessionId, cols, rowsnull
pty_killsessionIdnull

Shell / misc

CommandArgsResult
run_commandcommandcombined stdout+stderr string
get_cwdworking directory string
chat_check_installcommand (agent id)boolean

File system

CommandArgsResult
read_filepathfile text
read_file_base64pathbase64 string (images etc.)
write_filepath, contentnull
upload_filepath, content (base64)null
download_filepathbase64 string
read_directorypath, maxDepth?FileNode[]
list_filespathstring[] recursive relative paths
file_existspathboolean
create_filepath, content?null
create_directorypathnull
rename_entryfrom, tonull
copy_entryfrom, tonull
delete_entrypathnull
extract_zipzipContent (base64), destDirstring[] extracted paths
search_in_filespath, query, caseSensitive?, wholeWord?, regex?SearchMatch[]

Git

All git commands take path (the repo dir) plus command-specific args.

CommandExtra argsResult
get_git_statusGitStatus
get_git_difffileunified diff string
get_git_staged_difffileunified diff string
get_git_head_filefilefile text at HEAD
git_show_indexfilefile text from the index
git_addfileoutput string
git_stage_alloutput string
git_unstagefileoutput string
git_unstage_alloutput string
git_discardfileoutput string
git_discard_alloutput string
git_commitmessage, amend?output string
git_undo_commitoutput string
git_loglimit?GitCommitInfo[]
git_commit_diffcommitunified diff string
git_stash_listGitStashInfo[]
git_stashoutput string
git_stash_popoutput string
git_pushoutput string
git_fetchoutput string
git_pulloutput string
git_revertcommitoutput string
git_initoutput string
git_branch_listGitBranches
git_checkout_branchname, create?output string
git_mergefromRefoutput string
git_merge_abortoutput string
git_resolve_conflictfile, sideoutput string

Agent chat (kilo / opencode)

CommandArgsResult
chat_streamcommand, args?, cwd?, apiKey?, mode?, attachments?, requestId?fires chunk/done events; → null
chat_cancelid{ cancelled, reason? }
chat_modelsagent, apiKey?{ id, label }[]
chat_stream runs a thin agent client against a long-lived serve process the server manages per agent. The frontend subscribes to events before invoking so no early chunk is missed, matches chunks by requestId, and reconciles with chat-stream-done.