Table mode
A typed, real-time spreadsheet for humans and agents. Every row is a JSON object; every column is a schema entry with a type. Edits land live across every open tab and every connected agent. (Looking for prose, briefs, or narrative bodies instead? See doc mode.)
content-pipeline
Column types
textlongtextnumberstatuspersondateurlcheckboxselectCell selection & range
Click any cell to select. Shift-click another cell to extend the selection into a rectangle. Hold Shift while pressing arrow keys to grow the range one cell at a time. ⌘A / Ctrl+A selects every visible cell. Selection is the unit that copy, paste, drag-fill, and Delete operate on.
Row selection & bulk actions
Separately from the cell range, you can select whole rows via the checkbox that appears when you hover a row number. Row selection uses the same conventions as Finder / File Explorer:
- Click a row checkbox to toggle that row. The clicked row becomes the new range anchor.
- Shift-click another row to select every row from the anchor to the clicked row, inclusive — the same gesture as "select 20 rows at once" in a spreadsheet.
- ⌘-click / Ctrl-click another row to add (or remove) it without moving the anchor, so you can build a disjoint multi-selection and still Shift-extend later.
- With rows checked, Delete / Backspace deletes those rows; the bulk-action bar in the toolbar also shows a Delete button. Without any rows checked, Delete falls back to clearing the cells in the current range.
- The header-row checkbox toggles Select all (visible rows only — filters and hidden rows are respected).
Copy, paste, cut, fill
- Copy (⌘C / Ctrl+C) writes the selected range to the clipboard as TSV — paste it into Excel, Google Sheets, Numbers, or any text editor and the rectangle preserves shape.
- Paste (⌘V / Ctrl+V) reads the clipboard, parses TSV (handles quoted cells, embedded tabs/newlines), and pastes into the range starting at the anchor. Pastes wider/longer than the current sheet are clipped to the available cells.
- Cut (⌘X / Ctrl+X) copies the selected range to the clipboard, then clears the same range in one atomic step.
- Drag-fill the small accent square at the bottom-right of the selection — drag down to fill. Numeric and date sequences (e.g. 1, 2, 3 → 4, 5, 6 or 2026-01-01, 2026-01-02 → 2026-01-03) extrapolate; everything else cycles the source values.
- Delete / Backspace clears every cell in the range (or deletes the checked rows if any are selected).
Creating & editing columns
Click the + icon on the rightmost column to add one. Right-click any column header (or use the ⋯ menu on hover) to Rename, Sort, Add description, Hide, or Delete. Drag the header to reorder; the new position persists. Hidden columns appear as a chip next to the rightmost header — click to unhide.
Column descriptions show as a tooltip on hover, so the column contract (e.g. "ISO date, in local timezone" or "status: one of drafted/queued/active") stays one keystroke away from anyone editing the cell.
Find & replace
Click Find in the toolbar to substring-match across every visible cell. Type a replacement and press Enter (or click All) to rewrite every match in a single bulk update. Only free-text columns (text, longtext, url) are touched — structured types (status, person, date, select) are left intact so a free-text replace can't corrupt them.
Export to CSV
Click Export to download every visible row as a UTF-8 CSV (BOM-prefixed so Excel reads it without re-encoding). With a range selected, the menu offers a Selection · CSV option that exports just the rectangle — handy for sharing a slice without leaking the whole sheet.
Programmatically:
curl -X PUT https://trydock.ai/api/workspaces/content-pipeline/columns \
-H "Authorization: Bearer dk_..." \
-H "Content-Type: application/json" \
-d '{
"columns": [
{ "key": "title", "label": "GTM task", "type": "text", "position": 0, "width": 320 },
{ "key": "channel", "label": "Channel", "type": "select", "position": 1,
"options": [
{ "value": "linkedin", "label": "LinkedIn", "color": "#0A66C2" },
{ "value": "blog", "label": "Blog", "color": "#34D399" }
] },
{ "key": "status", "label": "Status", "type": "status", "position": 2,
"options": [
{ "value": "drafted", "label": "Drafted", "color": "#7A8B9E" },
{ "value": "queued", "label": "Queued", "color": "#F5B842" },
{ "value": "active", "label": "Active", "color": "#34D399" },
{ "value": "blocked", "label": "Blocked", "color": "#F87171" },
{ "value": "sealed", "label": "Sealed", "color": "#06D6A0" }
] },
{ "key": "owner", "label": "Owner", "type": "person", "position": 3 },
{ "key": "notes", "label": "Notes", "type": "longtext", "position": 4, "hidden": true }
]
}'Column fields you can set per entry: key, label, type, position, width, hidden, description, and options (for status and select).
Row CRUD
Rows are keyed by a stable id. Data is partial-patch merge on update, so you only send the fields you want to change.
POST /api/workspaces/:slug/rows
{ "data": { "title": "New LinkedIn thesis", "status": "drafted" } }PATCH /api/workspaces/:slug/rows/:id
{ "data": { "status": "sealed" } }
// other fields untouchedPATCH /api/workspaces/:slug/rows/bulk
{
"updates": [
{ "id": "row_a1...", "data": { "status": "active" } },
{ "id": "row_b2...", "data": { "status": "active", "owner": "Argus" } },
{ "id": "row_c3...", "data": { "status": "blocked" } }
]
}
// All-or-nothing: if any id is unknown, no row is updated.
// Cap: 500 updates per call. Each row in the batch costs the
// principal one row.updated event for SSE subscribers.DELETE /api/workspaces/:slug/rows/:idSee the full REST API reference for list/paginate/sort options.
Concurrency model
- Different rows = no conflict. Any number of agents can write in parallel.
- Same row, different fields = merged by the server (PATCH is field-level).
- Same row, same field = last write wins.
- Edits made by other collaborators flash pink in your tab; your own edits flash blue. Both fade in 700 ms.
- Recommendation: use
statusas a soft lock. Agents check the status before claiming a row.
Keyboard
What you don't get (yet)
- Formula columns (
=SUM(price, qty)) — on the roadmap. - Per-column data validation rules.
- Row grouping and pivot views.
Related
- Rows API — REST surface for the same cells (single row, bulk, move between surfaces, history).
- Surfaces API — manage the table tabs that hold rows.
- Cell comments — anchor a thread to a single cell.
- Keyboard shortcuts — sheet navigation, copy/paste, find & replace.