zudo-text

検索したい単語を入力

いつでも検索バーを開ける

Agent task recipes (MCP)

MCP integration is organized by tool family: it tells you what each tool does. This page is organized by intent. Each recipe below starts from a task you actually have — find something, revise a note, undo a batch of edits — and gives you the sentence to type, the tool sequence that follows from it, and the one thing that will bite you.

What you actually run

The first surprise is that the zudo-text command-line program is not something you type tasks at.

  • zudotext-mcp is a stdio MCP server, not a task-command CLI. It accepts only --help and --version. There are no workspace subcommands; it exists to speak the Model Context Protocol over stdin and stdout, and it is configured entirely through environment variables.

  • The CLI you talk to is claude or codex. Once the server is registered with your harness, the harness launches it for you and calls the zudo-text tools on your behalf. You never start zudotext-mcp by hand.

  • zudotext-mcp-install-skill is the package's only other CLI, and it installs the safety policy skill. It performs no workspace work — it writes a SKILL.md and stops.

So the end-to-end shape of every recipe on this page is the same. Open a terminal and start your harness:

claude
# or: codex

Load the packaged policy skill — /zudotext-authoring in Claude Code, $zudotext-authoring in Codex — and then type your request in plain English. Every caveat and confirmation gate on this page comes from that skill, so a session that skips it gets none of them:

List the notes under inbox/ and show me the three most recently changed.

That is the whole interface. The harness picks the tools; the recipes below say which ones it ought to be picking, so you can spot the moment it goes somewhere you did not intend.

Installing the package, minting a workspace-bound token, and registering the server are covered once, in MCP integration — do that first.

One rule before any write

For a generic authoring session that may write documents, the agent calls begin_authoring_session(label) before its first mutation.

This is not an optional trick for large batch edits. It is the packaged skill's standing requirement, and it is what makes the rest of the history tooling usable: the session checkpoint is the boundary that get_checkpoint_summary and get_checkpoint_restore_manifest later project changes against.

Caution

A checkpoint is a document undo boundary, not a workspace snapshot. Nothing is copied aside, assets are not covered, and rolling back to it is client-orchestrated work that can partially fail. Opening a session buys you a reviewable record of what changed — not a guaranteed way back.

The generic document recipes below assume this call already happened. The restricted approved-board routine has no checkpoint tool and uses its own revision/idempotency contract.

Recipes

Find something across the workspace

  • Ask for it like this — "Search reports/ for every note that mentions a rollback, and show me the matching lines."

  • What the agent does — search_notes(query, mode?, prefix?, limit?). The query is a regular expression, and the mode picks the shape of the answer: files (the default) returns matching paths, content returns matching lines with line numbers, and count returns per-file match counts. Naming a directory in your request lets the agent scope the scan with prefix.

  • Watch out — one search scans at most 2,000 candidate paths and reads content from at most 240 documents. A truncated result is incomplete, not proof of absence. If the answer matters, re-run it with a tighter prefix rather than treating a short list as the whole story.

Read a note, including a large one

  • Ask for it like this — "List what's under archives/, then read me archives/20260801-notes.md."

  • What the agent does — list_notes(prefix?, limit?, cursor?) to find the path, then read_note(path, maxBytes?, noteId?, expectedFileId?) to fetch it. archives/ is an ordinary workspace-relative prefix: there is no separate archive tool and no extra scope to grant. The read response also carries the note's current version, which is what any later write needs as its precondition.

  • Watch out — read_note returns a byte window, not a guaranteed whole document: 1 MiB by default and 8 MiB at most. The result says when it truncated, so on a long note make sure the agent read to the end before it summarizes, edits, or counts anything.

Draft a new note

  • Ask for it like this — "Create inbox/retro-2026-09.md with a heading and three empty bullets."

  • What the agent does — write_note(path, content) with expectedVersion omitted. An omitted version means create-only: the call fails if anything already exists at that path, so a fresh draft can never silently land on top of an existing note.

  • Watch out — creating is the only safe reason to omit expectedVersion. If the path turns out to be taken, the fix is to read the existing note and follow the revise recipe below. An agent that responds to the failure by retrying without a precondition has turned a create into an unguarded overwrite.

Revise an existing note

  • Ask for it like this — "Read inbox/spec.md, tighten the second section, and save it back."

  • What the agent does — read_note(path) for the current version, then write_note(path, content, expectedVersion) passing that version. The write replaces the whole document body, so the agent reconstructs the parts you did not ask it to change — including reproducing any existing YAML frontmatter byte-for-byte unless you explicitly asked for a field change.

  • Watch out — on a VERSION_CONFLICT nothing was written. That is the good outcome: someone else (usually the app on another device) changed the note first. The agent should re-read, reconcile against what you actually wanted, and retry with a fresh precondition — never force the write or replay the same body.

Delete a note safely

  • Ask for it like this — "Delete inbox/scratch.md, but show me its current version first."

  • What the agent does — read_note(path) to surface the current version and content, then a confirmation step, then delete_note(path, expectedVersion, idempotencyKey?, noteId?, expectedLocationRevision?, expectedFileId?). The version is required; there is no unconditional delete.

  • Watch out — this is a soft delete. It removes the live path and appends a recoverable tombstone; the retained file and its version history are not immediately erased, so a mistake can still be undone through the history tools. What it is not is invisible: the path disappears from list_notes at once, and the tombstone shows up in what_changed.

Recover a note you broke

  • Ask for it like this — "inbox/recovery.md got mangled — show me its saved versions and put back the one from before the rewrite."

  • What the agent does — list_note_versions(path, noteId?, expectedFileId?) to enumerate retained history, read_note_version(path, versionId, noteId?, expectedFileId?) to confirm the right one is being restored, then restore_note_version(path, versionId, expectedVersion, idempotencyKey, noteId?, expectedLocationRevision?, expectedFileId?).

  • Watch out — a restore creates a new head rather than rewinding. The bad revision stays in history and the note's version number goes up, so restoring twice is not "undo undo" — it is two more versions. Check the content with read_note_version before restoring, not after.

Rename or reorganize notes

  • Ask for it like this — "Move inbox/draft.md to archives/2026-09-draft.md."

  • What the agent does — a read for the current version, then move_note(fromPath, toPath, expectedVersion, idempotencyKey?, noteId?, expectedLocationRevision?, expectedFileId?). The move preserves the document's stable identity and its full version history, so list_note_versions on the new path still shows what happened before the move.

  • Watch out — a move does not rewrite Markdown references pointing at the old path. Links from other notes are not updated and will not error; they will just quietly point nowhere. If the note was linked, plan a search_notes pass for the old path and fix the referrers yourself.

Catch up on what changed

  • Ask for it like this — "What's changed in the workspace since we started?"

  • What the agent does — what_changed(afterCursor?, limit?), which returns ordered document upserts and delete tombstones after a change cursor, paging until it is caught up.

  • Watch out — the feed is document-only: asset uploads, downloads, and folder creates never appear in it, so it can never prove an asset is current. And "since we started" is not what the implicit cursor means: it advances on every successful response, so an omitted afterCursor really means "since the last what_changed call this process made" — and it resets to 0 when the MCP process restarts, so the first call after a restart replays the change feed from the beginning. Pass an explicit afterCursor whenever the window actually matters.

Review or roll back a batch of edits

  • Ask for it like this — "Show me the checkpoints, summarize the one we opened this session, and walk its changes back."

  • What the agent does — list_checkpoints() to find the boundary, get_checkpoint_summary(checkpointId, fromCursor?) to see what landed inside it, and get_checkpoint_restore_manifest(checkpointId) to get the work order. The manifest's entries are restore, delete, or noop; the agent applies them itself, one document at a time.

  • Watch out — there is no one-call or atomic rollback. The restore is client-orchestrated: the agent has to confirm the workspace head still matches the manifest's expectation with a fresh explicit what_changed walk, and it stops at the first conflict. A stopped rollback leaves the workspace partly rolled back, so insist on an honest report of which documents were actually restored.

Stash a work log

  • Ask for it like this — "Save this session's notes as a work log under the project sync-server."

  • What the agent does — stash_log(project, title, content, noteId, idempotencyKey, createdAt), which writes one dated Markdown document under logs/ that syncs to every device and shows up in the app.

  • Watch out — it never overwrites: a same-day collision takes the next numeric suffix instead. The filename convention and the frontmatter it writes are in The log-stash recipe.

Work with attachments

  • Ask for it like this — "Check my storage usage, then upload /absolute/path/to/diagram.png into the workspace as diagrams/diagram.png."

  • What the agent does — get_asset_usage() first, because quota or a soft lock can reject the creation outright. Then create_asset_folder(path, idempotencyKey) for a new destination folder, and upload_asset(sourcePath, path, idempotencyKey). Coming the other way it is download_asset(path, destinationPath), and list_assets() shows what is already there. Asset paths are their own namespace, separate from the document tree and with no assets/ prefix of their own: an asset stored at diagrams/diagram.png is what a note references as ../assets/diagrams/diagram.png.

  • Watch out — transfers cross a local-path boundary in both directions. An upload reads an explicit absolute local file, which must be a regular non-symlink file and is capped at 25 MiB of plaintext; a download writes only to a new absolute local path and never overwrites an existing file. Confirm the exact source and the exact destination before either runs.

Delegate open-ended work

  • Ask for it like this — "Ask the zudo-text cloud agent to suggest how to restructure my reports/ notes."

  • What the agent does — ask_zudo_agent(message, conversationId?). Omitting conversationId uses this process's default conversation; passing the id a previous call returned continues the same thread for chained refinement.

  • Watch out — this is the only tool that costs AI turns. Direct tools spend none, while every admitted ask_zudo_agent call spends one of your shared 100 AI turns per UTC day at admission — even if that turn later fails. And an edit it hands back is a proposal, not a change: it is applied only when the agent composes the reviewed body and writes it with write_note before the preview expires, using the preview's base version as the precondition. Reach for a direct tool whenever the path and the operation are already known.

What you can't ask for

Three different reasons an ask does not go through. Keep them apart: the first two are walls, and the third is a judgement call you are allowed to make.

Unsupported — the tool does not exist

No amount of rephrasing helps here, and the packaged skill explicitly forbids emulating the missing operation out of the tools that do exist.

  • Asset rename, move, delete, replace, or delete-and-recreate. The narrow asset family is deliberately create-and-read only. "Delete it and upload it again" is not an available workaround — it is the specific emulation the policy prohibits.

  • One-call or atomic checkpoint rollback. The manifest is a work order the client executes step by step. There is nothing to ask for that turns it into a single transaction.

Read-only by policy

The tools would technically write these, and that is exactly why the policy says not to.

.zudotext.settings.json, frameset state, and pins are whole-document last-writer-wins state. The running app can clobber an automation edit without noticing, and a malformed settings document can silently fall back to defaults — a failure that looks like the app losing your preferences rather than like a bad write. Have the agent read these; change them in the app.

Possible but risky, or simply unverified

Not forbidden. Not proven safe either. Decide deliberately.

  • Generic board rewrites — keep whole-document Kanban rewriting read-only. Use the restricted format-aware routine below with the matching captured-base UI writer. Older apps can still overwrite concurrent edits during debounce. Todo, timeline, mindmap, spreadsheet and slides have separate persistence implementations whose agent-write safety remains unverified.

  • Directive syntax — emitting or rewriting zudo-text directives, including admonitions and layout media, is unverified round-tripping. Ask the agent to preserve existing directive text rather than reflow it.

When a write is refused or gated

If the agent stops and asks before doing what you told it to, that is the packaged skill working as designed. By default it obtains owner confirmation immediately before each of these, showing you the target, the current version, and the expected effect:

  • replacing an existing whole note with write_note

  • delete_note

  • move_note

  • restore_note_version

  • executing a checkpoint restore manifest

  • applying a cloud-agent edit preview

Note that ordinary replacement is on that list even though it already has a version guard — the guard stops a conflicting write, not a wrong one, and the call still replaces the complete body. Asking for authoring work does not by itself waive the confirmation.

The policy is owner-editable: it lives in the installed zudotext-authoring/SKILL.md, and you may change it. Doing so makes the installer's byte-exact --check fail by design — that failure is how an intentional local customization stays visible. Back the customization up before running --update, which replaces the file, and reapply it afterward.

Portable approved-board routine

Use this routine only with the restricted Kanban connection. It is shared state: it does not start an agent, schedule work, watch forever, or guarantee background progress. A successful conditional move is not a durable task lock. Respect the host's write confirmations; tool visibility and annotations never waive them.

  1. Call list_kanban_boards() and choose only a returned, user-approved boardId. Call get_kanban_board(boardId, offset?, limit?), following nextOffset until null when inspecting the full board. If revisions differ across pages, restart the read. columns contains ordered stable IDs; columnLabels maps each ID to its effective display label. Match the user's intended label to the map and retain its ID; never assume labels such as Todo, Doing or Done exist or are unique. Resolve an ambiguous label before writing.

  2. Select the requested task by its returned reference, then call get_kanban_card(boardId, card). Keep its complete body, source column and revision. Do not derive an ID from a title, filename or model guess.

  3. Resolve the intended queue, active and completion columns from the user's workflow and returned ID/label map. If unclear, ask before claiming. Claim with move_kanban_card(boardId, expectedRevision, idempotencyKey, card, column, expectedColumn, position?): use the inspected revision, observed source column ID and chosen active column ID. Display labels never substitute for IDs. Retain the request and a fresh operation key before sending. Start work only after confirmed success. If another agent wins, stop and re-read; do not move the already-claimed card again or treat that conflict as permission to work.

  4. Perform the requested work within its own authorized tools and repository. Re-read the card before each progress write. Use update_kanban_card with only the fields being changed, preserving the freshly read body when adding progress, blockers, verification results and actual result/PR links. body replaces that field; it is not an append operation. Omit unchanged fields.

  5. Verify the actual result and report it on the card. Move to the selected completion column with a fresh read and conditional move only when the user's completion criteria are met. An attempted command, opened PR, mock test or unavailable check is not proof of delivery. Record blocked work honestly. Archive/restore only when requested, using the same revision/key discipline.

After response loss, retry the identical request with the same idempotency key; do not generate a new key or advance its expected revision. If the outcome is still unknown, stop before dependent work. On VERSION_CONFLICT, re-read and reconcile intent with current content; a changed request needs a new key. Never blindly rebase a stale body onto a new revision. A receipt contains committed references, not a new board revision: read again before the next mutation.

For WORKSPACE_LOCKED or KEY_SESSION_EXPIRED, return the user to the first-party connection screen for explicit unlock. Revoked access requires a newly approved connection; missing board/scope access requires human review, not generic tools. Never ask for passwords, raw keys or lease handles in chat. The restricted profile has no begin_authoring_session or checkpoint tools; do not request them or fall back to generic whole-document writes.

Setup and named-client acceptance are documented in Kanban agent connections.

See also

Captured document identity

Canonical notes have a permanent noteId UUID and display number; their paths can change. After read_note, retain the returned noteIdentity.noteId, noteIdentity.locationRevision, and body version. Supply these as noteId, expectedLocationRevision, and expectedVersion for update, delete, move, or restore, together with a caller-stable idempotencyKey. Do not substitute a newer version or the current occupant of an old path when retrying. Locate the same UUID and review the new body before authorizing a different edit. Reads and history reads accept noteId to reject a reused path.

Creating a Note Tray note requires a newly minted UUID in noteId and a stable idempotencyKey; omit expectedVersion. Keep the UUID, key, destination and exact body across an uncertain response or process restart. The server assigns the permanent display number. An ordinary root/internal document stays unregistered: its read returns a separate fileId, passed as expectedFileId with the captured version for mutations. Never pass an ordinary file ID as a note UUID or supply both identity fields. A workspace that still needs enrollment must be opened in the current app; there is no path-only creation fallback.

stash_log additionally requires the captured createdAt ISO UTC timestamp, noteId, and idempotencyKey. Reuse the entire tuple and original content on retry. It changes a filename suffix only after a definite collision; uncertain responses retain the original attempt. Read/write/stash results expose identity metadata in structuredContent as well as readable text.

External cloud-agent previews retain workspaceId, target, baseVersion, baseContent, and operation/admission metadata. A reviewed generic write_note must use that original target and body version; metadata does not grant external clients access to built-in Assistant admission or Apply routes. Missing or foreign-workspace preview identity is rejected.

Search results retain structuredContent.documents: the path, file ID, body version and optional canonical note identity captured for each matched body. Carry the matched noteId (or ordinary fileId as expectedFileId) into subsequent reads/history. A moved or reused path must never select a different result silently.