Notes
A note is a collaborative Markdown document. People edit it in the browser in
real time; dreamlake notes is how a script or an agent reads and edits the
same document from a shell.
The commands are pipe-friendly on purpose: read writes the body to stdout and
nothing else, write takes text from a file or stdin, and --json is there
wherever the readable form would be awkward to parse.
Finding a note
Which namespace
Notes belong to a namespace, and the default is your personal one — not an organization you belong to. An organization's notes live in its own namespace and are only reachable by naming it:
--namespace works on every command below. notes list --shared is the one
exception that crosses namespaces: it lists what other people shared with you,
wherever it lives.
A note is named by its slug, its title, or its id. All three work wherever
<note> appears below.
search is current: before querying, it flushes the notes anyone has open in
this namespace, so a sentence a colleague typed seconds ago is findable. You
do not have to wait for anything.
search also says where in each note it matched:
Go straight to that section — notes read runbook --section deploy — instead
of reading the whole note to find it. The most specific section is listed
first.
search matches titles and bodies, case-insensitively, by substring — so a
phrase inside a note finds it, and so does a fragment of an identifier like
LAKE_REMOTE. Chinese and other non-spaced scripts match the same way.
A note last written before bodies were indexed matches on its title only, until someone edits it or an administrator runs the one-off backfill.
Creating
Titles may repeat; the slug gets a suffix to stay unique, so the command prints the slug and id it actually made rather than the title you asked for.
Reading
sections lists what you can address:
A section is a heading plus everything under it, up to the next heading of
the same or a higher level — so install contains macos. The anchor is a
slug of the title, with a numeric suffix when titles repeat (setup,
setup-2). Text before the first heading is addressed as preamble.
Writing
A section is replaced verbatim, heading included — which is how you rename one. Leave the heading out and the section stops being a section.
Adding and removing sections
--after places the new section past that one and its subsections —
anything else would drop it inside the section you named. The heading is part
of the text, so you pick the level: a ### can go under a ##.
insert prints the new outline, because the anchor is only knowable afterwards
— a duplicate title takes the next free suffix.
rm-section removes the subtree too. That is what the section is; leaving the
subsections behind would promote them into the previous one.
Writing while other people are in the note
Every write is a real-time collaborative edit. The server joins the note's collaboration room and applies your change there, so anyone with the note open watches it appear — and it merges with what they are typing, the same way two people's edits merge.
That is true of all of them: write, append, patch, add-section,
rm-section. You do not have to wait for people to leave, and nothing is
locked.
The precondition is a different thing
Collaboration handles two edits arriving at once. It does not help with an edit built from a document that has since changed — read a note, spend a minute deciding, write the whole body back, and you would erase what happened while you were deciding.
So a write also sends the version it was based on. If the note moved in between, it is refused rather than applied:
| Exit | Means | Do |
|---|---|---|
3 | The note changed since you read it | Re-read, redo the edit. Retrying as-is fails again. |
4 | The realtime service could not take the write, and people are editing | Transient — wait a few seconds and retry. |
5 | Your diff no longer applies | Re-read and regenerate it. |
Exit 4 is an infrastructure signal, not a queue. It means the collaboration
room was unreachable AND somebody is connected — the fallback (writing the
archive) would reset the room and cost them whatever they have not saved, so
the command refuses instead. With the service healthy you will not see it.
Pinning a version yourself
read --json gives you the validator, which you can hold across a longer edit:
Overwriting on purpose
--force is the only way past the check. Overwriting a colleague should be
something you typed, not something that happened.
Patching
A unified diff carries its own precondition — the context has to match — so a document that moved refuses the patch instead of taking half of it.
Permissions
Reading needs read access; writing needs write access. A read-only share link gives the first and not the second — reads work, writes fail with "read-only access to this note". A note you cannot read at all reports as not found.
Command summary
| Command | Does |
|---|---|
notes create <name> | Make a note, optionally with a body |
notes list [--shared] | Notes in the namespace, or shared with you |
notes search <query> | Match note titles and bodies |
notes sections <note> | The outline, with anchors |
notes read <note> [--section <anchor>] | Body or one section, to stdout |
notes write <note> [--section <anchor>] | Replace body or section |
notes insert <note> [--before|--after] | Add a section |
notes rm-section <note> <anchor> | Remove a section and its subtree |
notes patch <note> | Apply a unified diff |
notes append <note> | Add to the end |
Every one of them takes --namespace, --json, and the usual connection flags.
write, patch and append take --if-match and --force.