-
cockpit send [--tab-id <id>] [--enter] <text> — type literal text; add
--enter to submit it (equivalent to a send-key Enter right after).
--focused targets whichever tab the human is looking at (the app resolves
it) — meant for tools driven by the human, not for agent orchestration, where
an explicit --tab-id is what keeps you from typing into the wrong tab.
-
cockpit send-key [--tab-id <id>] <Key>... — press key(s): Enter, Tab,
Escape, Space, BSpace, Up/Down/Left/Right, Home/End,
PageUp/PageDown, Delete, and C-<letter> (e.g. C-c = Ctrl+C).
-
cockpit new-tab [--cwd <dir>] [--title <name>] [--split h|v] — open a new
terminal tab in the app and print its id (t12). --cwd defaults to
your current directory; --title sets the stable tab label (so send/
read-tab can target it by name). Without --split the tab opens in the
same pane (next to yours); --split h (or right) splits side by side,
--split v (or down) stacks — tmux semantics. Capture the id to drive it:
id=$(cockpit new-tab --cwd ~/proj --title Worker --split h)
cockpit send --tab-id "$id" --enter "npm test"
-
cockpit close-tab [<label|tab-id>] — close a tab and print its id: the
counterpart of new-tab. Without a target it closes YOUR OWN tab, which
ends the shell you are typing in — pass the target explicitly unless that is
what you mean. Closing the last tab of a split removes the split; closing the
last tab of a workspace leaves an empty tab behind (same as the tab's "x").
id=$(cockpit new-tab --cwd ~/proj --title Worker)
cockpit close-tab "$id"
-
cockpit open [--tab-id <id>] <file> — open the file in the app's viewer
(tab next to the terminal). cockpit <file> is the shortcut. The path is
resolved against the tab cwd (relative, ~ and absolute all work). Any type
opens as text — including extensionless ones (.zprofile, Makefile).
-
cockpit browse <url> [--json] — open the app's built-in browser tab at
<url> (e.g. a dev server you just started: cockpit browse http://localhost:3000). A browser tab already open on the same host:port is
reused (it navigates/reloads instead of duplicating). Schemeless URLs get
http:// for localhost targets and https:// otherwise. On platforms
without an inline webview (Linux) the URL opens in the system browser —
--json output tells you which happened: {"mode":"inline"|"system","url":…}.
-
cockpit db <list|schema|query|run|execute> — query the workspace's
databases. Connections are registered in .cockpit/databases.json (Database
panel); SQLite files in the repo are auto-detected. Output is one JSON
line: {"ok":{columns,rows,rowCount,truncated,elapsedMs}} or
{"error":{kind,message}} (exit 1). The app executes everything — you never
see credentials. Examples:
cockpit db list — available connections (name, engine, target).
cockpit db schema --db dev-local / … --db dev-local orders — tables /
columns of a table.
cockpit db query --db dev-local --sql "SELECT …" [--limit N] — rows are
arrays (column order matches columns); truncated: true means the limit
cut the cursor — raise --limit if you need more.
cockpit db execute --db dev-local --sql "UPDATE …" — returns
affectedRows. Connections are read-only for agents by default: any
write is rejected with kind read_only_connection until the human enables
"Allow writes (agents)" on the connection in the Database panel — if you
hit it, ask the human instead of working around it. db list shows each
connection's access field (read | readwrite).
cockpit db run <file.dbq> — runs a .dbq file (SQL with -- db: /
-- limit: comment frontmatter). Prefer writing a .dbq when the human
should see the result too: the app shows it as a query tab and re-runs it
every time you save the file.
- Outside a Cockpit tab, add
--workspace <id|path>.
-
cockpit http <list|run> <file.http> — runs HTTP requests written in a
.http file (REST Client / JetBrains HTTP Client syntax: ### separates
requests, @name = value declares a variable, {{name}} interpolates it).
cockpit http list api/users.http — the requests in the file, with their
index, name, method and URL.
cockpit http run api/users.http [--request <name|index>] — runs one
(default: the first). Output is one JSON line: {"ok":{"status":200, "headers":{…},"elapsedMs":12,"json":{…}}}; the body comes back as json
when it parses as JSON, otherwise as body. A 4xx/5xx is a normal
response — check status, not the exit code.
- Prefer writing a
.http when the human should see the request too: the app
renders the same file as a request tab (editor + response), so they can
re-run and tweak it themselves.
- Outside a Cockpit tab, add
--workspace <id|path>.
-
cockpit redis --db <conn> <CMD> [args...] — Redis/cache command. One
JSON line reply. e.g. cockpit redis --db cache HGETALL user:42. Covers
Redis/Valkey/KeyDB.
-
cockpit mongo --db <conn> [--database <name>] --command '<json>' — MongoDB
runCommand. The command is a runCommand document, e.g.
cockpit mongo --db app --command '{"find":"users","filter":{"active":true}}'.
Output: one JSON line {"ok": <reply>} / {"error":{kind,message}}.
Documents use relaxed extended JSON ({"$oid":…}, {"$date":…}) both ways.
- Which database it runs against: the one in the connection URL's path,
if it has one; otherwise the one the human picked in the Database panel;
otherwise the command fails and the error lists the databases available.
--database <name> overrides all of it for that call only — it never
changes what the human is looking at, so prefer it whenever you are not
sure. Atlas URLs (mongodb+srv://…/?…) carry no database, so a connection
can legitimately have none until someone picks one.
- Discover databases with
--command '{"listDatabases":1}' (routed to
admin for you — that is the only database the server accepts it on), then
collections with
--database <name> --command '{"listCollections":1,"nameOnly":true}'.
Running listCollections without knowing the database is the classic
mistake: you get system.users/system.roles/system.version back, which
is the admin database answering — not an empty deployment.
-
Browse commands open a view for the human — they return no data. Use
them to show what you found (after investigating with the commands above),
not to query:
cockpit redis browse --db <conn> [--pattern 'user:*'] — opens the
editable Redis key table, pre-filtered. On an already-open table the
pattern replaces the current filter.
cockpit mongo browse --db <conn> [--database <name>] <collection> [--filter '<json>'] — here --database does change the connection's
current database, because the tab you open becomes what the human sees —
opens the Mongo collection browser (JSON document cards) pre-filtered.
The filter lands in the visible filter bar, editable by the human.
-
Registering a connection (.cockpit/databases.json at the workspace
root — the file behind cockpit db list and the Database panel):
{
"databases": [
{"name": "dev-local", "url": "sqlite:./app.db", "savePassword": false},
{"name": "app", "url": "postgres://user@localhost:5432/appdb", "savePassword": false},
{"name": "cache", "url": "redis://localhost:6379/0", "savePassword": false},
{"name": "docs",
-
Connecting through a bastion (SSH tunnel) — a connection may carry an
optional ssh block. The app opens the tunnel and points the driver at a
local port; every cockpit db|redis|mongo command works unchanged.
{
"databases": [
{
"name": "prod",
"url": "postgres://appuser@localhost:5432/appdb",
"savePassword": true,
"ssh": {
"host": "bastion.acme.dev",
"port": 22,
"user": "deploy",
"keyPath": "~/.ssh/id_ed25519",
"savePassphrase": false
}
}
]
}
With a tunnel, the database host/port are resolved from the SSH
server — localhost means the bastion itself, not your machine.
Authentication is key only; the block never holds a secret (the
passphrase, when the key has one, lives in the OS keychain).
-
cockpit read-tab [<label|tab-id>] [--lines N] [--offset N] [--from-start]
(alias: read-pane) — read a tab's rendered output as plain text (no
ANSI escapes; covers TUIs on the alt-screen too). Without a target it reads
your own tab; a target may be a stable tab label or a tab-id. Default
window: the last 100 lines (tail). --lines N sets the window size
(server cap 2000); --from-start anchors at the beginning of the buffer
instead of the end; --offset N skips N lines from the chosen anchor
(pagination: read the last 100, then --lines 100 --offset 100 for the 100
before those). Output is always chronological (top→bottom) — the flags only
pick the window.
-
cockpit read-task <task-id> [--lines N] [--offset N] [--from-start] — same
windowed read, but for a task run's output (the Task Run feature). Works
even if no task-output tab is open, but only for tasks that ran this boot.
Discover ids with cockpit list-tasks (never guess them).
-
cockpit list-tasks [--json] — tasks of your workspace (the one owning
the current tab, or --tab-id's): id, label, kind (watch|oneShot),
source (detected|manual), running, hasOutput (read-task has output
to read). Ids are stable per workspace: npm:<script> (package.json
scripts), flutter:run/flutter:test, json:<label>
(.cockpit/tasks.json).
-
cockpit list-tabs [--json] (alias: list-panes) — active tabs: id,
kind (terminal|agent|file|task), title (dynamic), label (manual stable
name, or null), workspaceId (opaque UUID), workspacePath (workspace root
on disk), working, and taskId on task-output tabs (the id read-task
accepts). Resolve a tab by its stable label, not the dynamic title.
-
cockpit list-workspaces [--json] — open projects: id (opaque UUID),
name, path (root on disk), tabs.
-
cockpit orchestrate <file.ckp> [--json] — apply a pane layout to the
current workspace: opens the terminals/splits declared in the file and types
each pane's command. Idempotent merge: a pane whose name already exists
as a tab label is skipped (running it twice is a no-op). Prints
created:/skipped: (or {"created":[],"skipped":[]} with --json).
Read what another tab printed (e.g. check on a worker, debug a failure):