# CLI commands

> Every dockito command and option, from the CLI's own help.

This page is built from the CLI's own help, so it always matches the release. In a terminal, `dockito <command> --help` shows the same text.

Every command takes `--json` for machine-readable output and `-w, --workspace <slug>` for a workspace other than your personal one. A `<doc>` is a doc's link or its 12-character code.

## sync

Mirror a folder into a project.

```sh
dockito sync <folder> --to <project>
```

Mirrors a local folder into a project: subfolders become folders, and each file updates the doc with the same file name in the same folder, or becomes a new doc there. Only files whose content changed are sent. Nothing is moved or deleted in Dockito. The CLI remembers nothing: pass `--to` every time.

Docs made by sync are private.

| Option | |
|---|---|
| `--to <project[/folder]>` | Where it goes (required; `dockito tree` lists places) |
| `-w, --workspace <slug>` | Another workspace |
| `--create` | Make the project if it doesn't exist |
| `--fold` | Put folders deeper than 2 into the deepest allowed; clashing names get the left-out folders in front |
| `--dry-run` | Show the plan, change nothing |
| `--yes` | Apply a plan that makes a project or folders |

It always shows a plan. Making a project or folders waits for `--yes`: show the plan to the user first. Sending docs into folders that exist just runs.

```sh
dockito sync docs --to handbook
dockito sync docs --to handbook --create --fold --dry-run
```

## publish

Publish files; the same name in that place updates its doc.

```sh
dockito publish <file...>
```

Publishes Markdown or HTML files. A file with the same name in that place updates its doc (same link, a new History entry); otherwise it's a new doc. Unchanged files are skipped. A .csv becomes a new live sheet, typed as Excel opens it; after that it changes with `dockito apply`, never by a file.

Docs are private: only people in the workspace can open them. Add `--public` only when the user clearly asked for a public link (anyone with the link, no sign-in). If they didn't say, keep it private. `--public` works only for a new doc; an existing private doc can be made public only from Share in the app.

| Option | |
|---|---|
| `--to <project[/folder]>` | Where (default: the workspace's Docs) |
| `-w, --workspace <slug>` | Another workspace (default: your personal one) |
| `-m, --message <note>` | Keep this entry as a saved point, with a note |
| `--public` | Make the new doc public (only when the user asked) |
| `--title <title>` | A new doc's title (default: the file name); an existing doc keeps its own |
| `--doc <doc>` | Update this doc (link or code) instead |
| `--new` | A new doc even if the name is already there |

```sh
dockito publish plan.md  # private, in your Docs
dockito publish plan.md --to handbook/specs  # private, in a folder
dockito publish plan.md --public  # the user asked for a public link
dockito publish q3.html --title "Q3 plan"  # named Q3 plan, not q3
```

## share

Who can open a doc; --private takes a public link back.

```sh
dockito share <doc>
```

Says whether a doc is private (only people in its workspace) or public (anyone with the link). `--private` makes it private again at once.

An existing doc is made public only from Share in the app; a new doc can be published public with `dockito publish <file> --public` when the user asks.

```sh
dockito share <link or code>
dockito share <link or code> --private
```

## tree

Every workspace, project and folder you can use.

```sh
dockito tree
```

Lists every workspace this login can reach, its projects and their folders, with doc counts, each written as the `--to` it takes. Places where you can only view or comment are marked: publishing there is refused. Docs themselves: `dockito ls`.

## ls

What's in a place.

```sh
dockito ls [project/folder]
```

Lists the docs (with their codes), projects and folders in a place: your workspace's top level, a project, or a folder. The place can also be given as `--to`, like publish. `-w` for another workspace.

```sh
dockito ls handbook/specs
dockito ls --to handbook/specs
```

## mkdir

Make a project or folders.

```sh
dockito mkdir <project/folder>
```

Makes whatever is missing: the project, then up to 2 levels of folders.

```sh
dockito mkdir handbook/specs/drafts
```

## move

Move a doc or folder.

```sh
dockito move <doc or project/folder> [place]
```

Puts a doc anywhere in its workspace (no place: the workspace's Docs), or a folder elsewhere in its project. The link stays the same.

Who can open it follows where it sits. A move that would let more people open it, or do more with it, is refused and names them: move it in the app, which asks first. A move that shuts people out says who.

| Option | |
|---|---|
| `--to <project[/folder]>` | The place, as publish takes it |
| `-w, --workspace <slug>` | Another workspace (for a folder) |

```sh
dockito move 5jyx8jjx6kc5 handbook/specs
dockito move 5jyx8jjx6kc5
dockito move handbook/drafts handbook/specs
```

## rmdir

Remove an empty folder.

```sh
dockito rmdir <project/folder>
```

Removes a folder with nothing in it. A folder with docs or folders in it stays, and nothing is deleted with it. Projects are removed in the app.

```sh
dockito rmdir handbook/specs/old
```

## open

Open in the browser.

```sh
dockito open <doc>
```

Opens a doc (link or code) in the browser.

## get

Download a doc, or read it in parts.

```sh
dockito get <doc> [-o file]
```

Prints a doc's file, or writes it with `-o`. Big docs can be read in parts. A sheet prints its outline: each sheet's columns, what's in them, and the version to apply changes at; `dockito read` gives its rows.

| Option | |
|---|---|
| `--outline` | Only the headings, each with the line it starts on |
| `--lines <range>` | Only these lines: 120-260, 120- (to the end) or 120 |
| `--text` | HTML as readable text: no tags, scripts or styles, often a few times shorter (Markdown is already text) |
| `--entry <n>` | A History entry (numbers from `dockito history`) |
| `-o, --output <file>` | Write it to a file |

```sh
dockito get <doc> --outline
dockito get <doc> --lines 120-260 --text
```

## read

A sheet's rows, a range or totals.

```sh
dockito read <doc> [range]
```

Prints rows of a sheet as a text table: row numbers, values as shown, and the version (v N) to apply changes at. A range, or a sheet's rows under its header row, filtered and sorted; with `--group` or `--totals`, totals instead. 200 rows unless `--limit` says, at most 1,000; page on with `--from`. `--chart` gives a chart's points instead.

[range]                  Tasks!A1:G40, Tasks!B:B, Tasks!3:5, a defined name, or E17 when there's one sheet `--sheet <name>`           A sheet or table's rows under its header row `--where <filter>`         "Area = Kitchen and Status &lt;> Done or Hours > 4": = &lt;> &lt; > <= >= contains, is empty, is not empty; dates as yyyy-mm-dd `--select <cols>`          Columns to show, by header or letter: ID,Status `--order-by <cols>`        "Due desc, ID"; empty cells go last `--group <cols>`           Group the rows by these columns `--totals <list>`          count, sum Hours, avg Hours, min Due, max Due `--from <n>`, `--limit <n>`  Which rows: from 1; 200 by default, 1,000 at most `--formulas`               Formulas with their results: =F2*50 → 50 `--styles`                 Formatting in words, merges, sizes, frozen panes; cells a conditional format colours say so `--csv`                    As CSV instead of a table `--chart <n>`              Chart #n's points as a table, as drawn (alone)

```sh
dockito read <doc> --where "Status = Blocked" --select ID,Owner,Due
dockito read <doc> --group Owner --totals "count,sum Hours"
dockito read <doc> "Tasks!A1:G20" --formulas
dockito read <doc> --chart 2
```

## apply

Change a sheet at the version you read.

```sh
dockito apply <doc> <changes.json>
```

Changes a sheet, read at `--base`: the version (v N) your last get, read or changes showed. Addresses, rows and headers mean what they meant then, wherever they moved since; so do chart and format numbers (#N, by order in the outline; a chart an earlier change here makes takes the next number) and sheet names (after a rename here, either works). Every change applies, or none: a cell someone changed since is refused, naming who (exit 1). Read again and apply on the new version. Prints each cell old → new and the new version.

The file (or - for stdin) is a list of changes, or &#123;"base": N, "ops": [...], "expect": &#123;...}} (cells that must hold these values before the ops, as at base). "sheet" can be left out when there's one. Each change: &#123;"set": "Tasks!E17", "value": "Done"} &#123;"set": "Tasks!B2:C3", "values": [["Tile grout", "Kitchen"], ["Vent", "Bath"]]} &#123;"update": &#123;"sheet": "Tasks", "where": "ID = T-104", "set": &#123;"Status": "Done"}}} &#123;"update": &#123;"sheet": "Tasks", "where": "Area = Kitchen and Status = Open", "set": &#123;"Status": "Done"}, "max": 50}}   max is 1 unless set; more matches than max are refused &#123;"append": &#123;"sheet": "Tasks", "rows": [&#123;"ID": "T-214", "Status": "Open"}]}} a column's formula and the formats of the row above carry into new rows, as in Excel &#123;"insertRows": &#123;"sheet": "Tasks", "after": 40, "count": 2}}, deleteRows &#123;"rows": "41:42"} or a list, "9, 16, 41:42"; moveRows &#123;"rows": "5:6", "after": 10}; insertCols, deleteCols, moveCols the same with letters &#123;"format": &#123;"range": "Tasks!1:1", "bold": true, "fill": "#fff2cc"}} cells, rows "1:1" or columns "F:F"; null clears a field: bold italic underline strike wrap   true or false size                                points, 1 to 409 font                                a font's name, as "Inter" color fill                          "#rrggbb" hAlign                              left, center, right or justify vAlign                              top, middle or bottom indent                              0 to 250 borderTop borderRight borderBottom borderLeft "thin #d0d5dd", or &#123;"line": "thin", "color": "#d0d5dd"}; lines are thin, medium, thick, dashed, dotted or double numFmt                              Excel's, as "$#,##0.00", "d mmm yyyy" &#123;"resize": &#123;"range": "Tasks!B:C", "size": 120}}, merge, unmerge addSheet, renameSheet, moveSheet, deleteSheet, sheetProps (frozenRows, frozenCols, hidden, tabColor), setName, deleteName, setTable, deleteTable &#123;"addTable": &#123;"range": "Tasks!A1:D40", "name": "Tasks"}}: a header row and banded rows in one change; a cell's own fill shows over them &#123;"validate": &#123;"range": "Tasks!D2:D", "list": ["Open", "Done"], "reject": true}}: a rule from row 2 down (rows added later too); reject refuses other values, else they're taken and marked. One kind each: list, from ("Lists!A2:A20"), checkbox (true), number (&#123;"between": [0, 100]}, "at most", "at least", …), date (&#123;"after": "2026-01-01"}), text (&#123;"contains": "x"}), email, url, length (&#123;"at most": 50}), formula ("=C2&lt;D2"); "help" is shown with a refusal; "remove": true takes it off &#123;"conditional": &#123;"range": "Tasks!D2:D", "text is": "Blocked", "format": &#123;"fill": "#f6d3d0", "bold": true}}}: the outline lists rules in order (format #N); the first that matches a cell wins; new ones go last. One condition each: empty, "not empty", "text contains", "text not contains", "text starts with", "text ends with", "text is", "date is", "date before", "date after" ("today", "past week", "2026-01-01", …), number (&#123;"greater than": 8}), formula ("=$F2&lt;TODAY()"), scale (&#123;"min": "#ffffff", "max": "#57bb8a"}, no format), duplicate, unique, top (10 or "10%"), bottom, "above average", "below average". Format: bold, italic, underline, strike, color, fill. "before": 2 or "first": true places it; &#123;"rule": 3, ...} changes or moves rule 3; "remove": true with rule or range takes rules off &#123;"replace": &#123;"find": "Lee", "with": "Priya", "in": "Owner"}}: find and replace as one change; "in" is a column by header or letter (its rows under the header) or a range ("Tasks!C2:C"); left out, the whole sheet ("sheet" names it). "with" may be "". "case": true, "whole": true (the whole cell), "regex": true (RE2; $1 in "with"), "formulas": true (change formulas; else one matches by its result and is left). Says what was left and why; over 100,000 cells changes nothing &#123;"chart": &#123;"range": "Tasks!A1:C40", "type": "column", "title": "Costs"}}: the outline lists charts as chart #N. "header" (first row names the series) and "labels" (first column labels the points; a scatter's x) are guessed when left out. Type: column, bar, line, area, pie, donut, scatter (first column: x), or "stacked column", "stacked bar", "stacked area", "doughnut", "horizontal bar"; "stacked": true for column, bar, area. "at": "E2", "below", "beside", "below chart #2" or "beside chart #2"; left out, beside the range on its first row, past whatever fills those rows (under a wide range when that's clear), never over filled cells or another chart (the sheet grows to fit). "width", "height" in px, 40 to 4,000 (left out: fitted, 480 × 300, wider past 24 points; a pie 420 × 300). "title" (left out: the series by the label column, "Kitchen and Bath by Month"), "x title", "y title"; "legend": right, bottom, top, none; "colors": ["#4285f4", null] per series. The answer says what it draws and warns about a total row or column, or a column with no numbers. &#123;"chart": &#123;"chart": 2, ...}} changes chart 2; &#123;"chart": &#123;"chart": 2, "remove": true}} removes it Values: a number, true, false, null (empty), a string ("=…" is a formula), &#123;"text": "=as typed"} or &#123;"date": "2026-10-19"}.

| Option | |
|---|---|
| `--base <n>` | The version you read |
| `-m, --message <note>` | Why, shown with the change in the sheet |
| `--dry-run` | Show what would happen, save nothing |
| `--undo <n>` | Take back your own change that made version n |
| `--key <key>` | A retry key (default: made from the request, so the same request on the same version applies once) |

dockito apply &lt;doc> changes.json `--base` 412 `-m` "close finished tasks" echo '[&#123;"set": "E17", "value": "Done"}]' | dockito apply <doc> - `--base` 412

## check

Problems in a sheet.

```sh
dockito check <doc>
```

Finds problems in a sheet, by rules: formula errors, a formula that breaks its column's pattern, a value typed over a column's formulas or a cell left empty among them, numbers or dates typed as text, totals that stop before their column does. Exits 1 when it finds any.

| Option | |
|---|---|
| `--sheet <name>` | One sheet (default: every sheet) |

## changes

What changed in a sheet.

```sh
dockito changes <doc> --since <v>
```

Lists what changed after a version, or since a time in UTC, oldest first: who, when, through what, with each cell old → new, named where it is now. Ends at the current version, to apply changes at.

| Option | |
|---|---|
| `--since <v|time>` | 412, 2026-10-13 or "2026-10-13 09:00" |
| `--max <n>` | At most this many changes (default 50, at most 200) |

## history

History entries.

```sh
dockito history <doc>
```

Lists a doc's History: entry, when, who, from where (upload, edit, cli, mcp), saved points with their notes, and the git commit. A sheet's entries are how each editing session left it: its version and everyone who changed it.

## restore

Make a History entry current again.

```sh
dockito restore <doc> <entry>
```

Makes an older entry the current one, as a new entry. Nothing is lost. A sheet is made as it was then in one change, which `dockito apply <doc> --undo <version>` takes back.

## save

Keep an entry as a saved point.

```sh
dockito save <doc> [entry] -m <note>
```

Keeps an entry (default: the current one; a sheet: as it is now) as a saved point, so History never drops it, with an optional note. A doc keeps up to 10.

## login

Sign in through the browser.

```sh
dockito login [--update]
```

Opens the browser, where you check a code and choose this login's access in each workspace: View, Publish or Everything. `--update` changes that access. `--no-browser` prints the link instead.

## logout

Sign out this machine.

```sh
dockito logout
```

Signs this machine out and removes its token.

## whoami

Who you are and what this login can reach.

```sh
dockito whoami
```

Your name, the login's expiry, and its access in each workspace.

## agent

What an AI agent needs to know.

```sh
dockito agent
```

Prints what Dockito is and how an AI agent should use this CLI.

## Environment

| Variable | |
|---|---|
| `DOCKITO_TOKEN` | Use this personal token instead of the login, for CI and scripts. |
| `DOCKITO_URL` | Talk to another Dockito address. |

## What agents read first

`dockito agent` prints this, and it heads `dockito --help`:

```text
Dockito hosts Markdown and HTML docs, and live sheets, at a short link,
with History.

  workspace  a person's or a team's space; its slug is in every link
  project    docs grouped in a workspace, with folders up to 2 deep
  Docs       a workspace's docs outside any project
  doc        one file. Publishing a file with the same name to the same
             place updates that doc and keeps its link
  History    every publish is an entry; -m keeps one as a saved point
  access     a login has View, Publish or Everything per workspace

For AI agents:
  - The CLI remembers nothing between runs. Run `dockito tree` to see
    where docs can go and `dockito ls <place>` for what's there.
  - Just a link to share: publish with no --to; it goes to the workspace's
    Docs. When it belongs in a project, ask the user where, never guess,
    and pass it with --to every time.
  - Docs are private: only people in the workspace can open them. Add
    --public (anyone with the link, no sign-in) only when the user clearly
    asked for a public link. If they didn't say, keep it private.
  - A folder of docs: `dockito sync <folder> --to <project>`. It shows a
    plan; show it to the user before running with --yes.
  - `dockito move` puts a doc or folder in another place; its link stays.
    A move that would let more people open it is refused: the user moves
    it in the app. `tree` and `ls` mark places you can only view.
  - `dockito <command> --help` explains each command. Use --json; on
    failure, read "error" and the commands it suggests.

Sheets: people and agents edit the same cells, live. Publishing a .csv
makes a new one.
  - `dockito get <sheet>` gives its outline (sheets, columns, what's in
    them) and its version, v N. `read` gives rows, `check` finds broken
    formulas, `changes --since N` lists what changed.
  - `dockito apply <sheet> changes.json --base N`, with N the version you
    last read. Addresses and rows mean what they meant then. If someone
    changed the same cells meanwhile, nothing applies and it says who
    (exit 1): read again, then apply on the new version.
  - Change rows by what's in them, not by row number: `update` with a
    filter ("ID = T-104"), and "max" when you mean several rows.
```
