DreamLake

Legacy commands

These commands remain available for existing scripts and targeted section/text operations. Their ETag checks differ from the current original-snapshot patch workflow. Use this page when you need write, append, replace, section mutation, or body-only reads.

Read and replace a body

bash
NOTE_ID=release-plan
dreamlake notes read "$NOTE_ID" --legacy --json > legacy-baseline.json
ETAG=$(jq -er .etag legacy-baseline.json)
jq -jr .text legacy-baseline.json > note.md
# Edit note.md, then preview and submit against the saved ETag.
dreamlake notes write "$NOTE_ID" --file note.md --if-match "$ETAG" --dry-run
dreamlake notes write "$NOTE_ID" --file note.md --if-match "$ETAG" --json > legacy-receipt.json
ACK=$(jq -er .etag legacy-receipt.json)
dreamlake notes read "$NOTE_ID" --legacy --if-match "$ACK" --json

Legacy JSON uses text and etag, not v2 content and revision. Keep the ETag exactly as returned, including quotes. Without an explicit --if-match, these mutations normally fetch a current ETag just before writing. That protects the request race, not the time spent editing an older local file. Always retain the ETag from the read that produced your draft.

insert, replace, and delete accept that quoted legacy ETag, not a modern rtc: revision. The CLI rejects that token mismatch before sending an edit. An actual changed ETag still returns a conflict; keep the draft and reconcile it. For concurrent merging, use notes patch --base-revision "$BASE_REVISION"; its default is merge, while --exact is opt-in. Legacy insert also uses RTC internally; successful insertion does not establish that a modern merge patch was saved correctly. Always verify the acknowledged snapshot and intended text.

Insertion --ind positions count Unicode code points in the exact retained source (Python len, JavaScript Array.from(text).length), not UTF-16 units.

--force bypasses that check on supported legacy mutations. It can overwrite concurrent work; it is not a conflict-recovery recipe. V2 patch rejects it.

Sections and appending

bash
# install.md must include the section heading.
dreamlake notes write "$NOTE_ID" --section install --file install.md --if-match "$ETAG"

A section includes its heading and descendants. Replacing it without its heading removes that section boundary. Refresh your baseline for each separate edit; the following are independent command forms, not a sequence sharing one ETag:

bash
dreamlake notes append "$NOTE_ID" --text $'\n## Changelog\n- Shipped\n' --if-match "$ETAG"
dreamlake notes insert "$NOTE_ID" --after install --file troubleshooting.md --if-match "$ETAG"
dreamlake notes insert "$NOTE_ID" --before install --file prerequisites.md --if-match "$ETAG"
dreamlake notes rm-section "$NOTE_ID" troubleshooting --if-match "$ETAG"

--after inserts after the section and its subsections. rm-section removes the whole subtree. The inserted heading determines its level; repeated titles get suffixed anchors. Inspect notes sections afterward.

Insert with a retained ETag

bash
NOTE_ID=release-plan
dreamlake notes read "$NOTE_ID" --legacy --json > legacy-baseline.json
ETAG=$(jq -er .etag legacy-baseline.json)
# Insert at the beginning of that exact source, with its original guard.
dreamlake notes insert --note "$NOTE_ID" --ind 0 --text 'Review: ' --if-match "$ETAG"
dreamlake notes read "$NOTE_ID" --json

Edit by text, pattern, or location

bash
dreamlake notes find "Draft" --note "$NOTE_ID" --json
dreamlake notes replace "Draft" --text "Published" --all --note "$NOTE_ID" --if-match "$ETAG" --dry-run
dreamlake notes replace --regex '(\w+)=(\d+)' --text '$1: $2' --all --note "$NOTE_ID" --if-match "$ETAG" --dry-run
dreamlake notes insert --text "New line" --line 10 --note "$NOTE_ID" --if-match "$ETAG" --dry-run
dreamlake notes delete "obsolete paragraph" --note "$NOTE_ID" --if-match "$ETAG" --dry-run

Review the preview, then remove --dry-run for the intended edit. Ambiguous single-match queries are refused; use --all deliberately. Patterns use JavaScript syntax, including named captures, $1, $<name>, and $&. Use -- before a positional query beginning with -, after all options.

For an HTML-source document, selectors target its source without reserializing the whole document:

bash
dreamlake notes select "#contact" --note "$NOTE_ID"
dreamlake notes replace "Contact us" --text "Talk to sales" --selector "#contact" --note "$NOTE_ID" --if-match "$ETAG" --dry-run
dreamlake notes insert --text "<li>New</li>" --selector "#list" --position append --note "$NOTE_ID" --if-match "$ETAG" --dry-run
dreamlake notes replace --html "<b>done</b>" --selector "#status" --note "$NOTE_ID" --if-match "$ETAG" --dry-run

Legacy diff and patch

bash
NOTE_ID=release-plan
dreamlake notes read "$NOTE_ID" --legacy --json > legacy-baseline.json
ETAG=$(jq -er .etag legacy-baseline.json)
dreamlake notes diff "$NOTE_ID" --legacy --since "$ETAG"

Plain legacy diff output is only the unified diff on stdout, with metadata on stderr. JSON returns diff, from, to, and etag. --context accepts 0–100 lines (default 3). No changes produce empty stdout. Unknown retained references are errors.

To upload a single-file diff prepared from that exact saved body:

bash
dreamlake notes patch "$NOTE_ID" --legacy --file draft.diff --if-match "$ETAG" --json

Legacy reads/diffs/patches require explicit --legacy; write, append, and the section/text mutation commands retain their own interfaces. Do not supply a v2 RTC revision where these commands expect a content ETag.

Concurrent edits and failures

Writes go through the collaboration service. They do not require other people to leave. A stale ETag rejects with exit 3; inspect current text and review a new edit. RTC unavailability is exit 4, and rejected patches are exit 5. Keep your draft when a request fails. Do not assume a lost acknowledgment means nothing was written, or use a forced archive replacement to recover.

For new agent workflows, prefer Editing with patches.

Presence command migration

CLI 0.28.x–0.30.x exposed notes presence <note> <action> and join --watch. CLI 0.31.0 removes those manual session controls. Use notes read <note> --linger for maintained participation, Ctrl-C to leave, or notes visit <note> for a brief visit. Attributed reads and edits register or refresh presence automatically.

notes presence <note> now reads the participant roster without joining. It prints text by default; --json is an explicit programmatic option. There are no direct notes join, notes heartbeat, or notes leave commands. The HTTP presence lease protocol remains available to SDK integrations and is used internally by linger; it is not a sequence CLI users need to manage.