# Changelog
## 0.11.0 - 2026-08-26
- **`delete_block` / `delete_page` can now report failure**: Roam servers (from the
corresponding Roam release) return a `{deleted: boolean}` report for deletes — an
explicit `deleted: false` renders as an error with new code **`NOT_FOUND`** — meaning
_the delete did not happen_ (on every current server, because nothing existed to delete).
It is a tool-level error result (`isError`, code in the JSON error payload, target uid in
the error context); the message distinguishes the benign causes — an ancestor deleted
earlier, a retry after a timeout — from a stale/mistyped/wrong-graph uid, and says NOT to
retry. `deleted: true` surfaces as `{success: true, deleted: true}`
(declared UNTYPED via `DeleteOutput` — `SuccessOutput.extend` with `deleted: z.unknown()`,
passthrough preserved — so no future server value can fail transport validation after a
committed delete). The error is self-describing; the READMEs and the opt-in `roam-syntax`
skill reference carry the human-facing compatibility and retry guidance.
**Version tolerance / cross-repo invariant:** an ABSENT `deleted` field means an older
Roam that doesn't report, which keeps the previous behavior exactly (checked strictly
with `=== false`). The report also carries a `reason` discriminator: `"not-found"` — or
an older server sending none — is the only cause today, and **only it** licenses the
"already gone, don't retry" copy. Any other `reason` is a newer server semantic this
version doesn't know, and renders a message that quotes it and explicitly does not claim
the target is gone. A future cause MUST use a new `reason` rather than inherit
`"not-found"`. A failed deletion commit on current servers arrives as an ordinary
error response (never a success envelope), so no report is involved.
- **Model-facing `delete_page` copy corrected:** the tool description previously said page
references were removed when their page was deleted. It now accurately says referrers are
de-linked in place — for example, `[[Page Name]]` becomes plain text `Page Name` — including
references in block strings and page titles, with tags and attributes similarly de-linked.
- CLI: `roam delete-block` / `roam delete-page` on a nonexistent uid now print the error
JSON and **exit 1** (previously exit 0 with success output).
- Internal contract change, **no observable difference today outside the deletes**: the write/UI
tools that used to hardcode `{success: true}` now pass the Roam server's `result` through,
merged under `success: true` (new exported helper `successResult`, from `core` and `local`).
Every action other than the deletes returns nothing today on all Roam versions, so those
results are identical to before; the point of the change is that a future server-reported
field reaches agents without a core release. The nine sites and the server-side consequence
(those payloads are agent-facing API from here on) are in `docs/architecture.md` §2e.
- Docs: `docs/architecture.md` §4/§6 rewritten for the hosted consumer's move from a caret range
to an **exact** core pin (2026-08-14) — nothing we publish reaches hosted without a deliberate
upgrade on their side. Records what they now pin about us (blob SHA-256 fingerprints,
`EXPECTED_API_VERSION`, the exact `dataTools` name list) and corrects a prior claim that
patches inside the pinned minor arrived automatically.
## 0.10.0 - 2026-08-02
- **`get_graph_guidelines` now returns a `roamSyntax` field** — a compact, graph-agnostic guide
to Roam's agent markdown (the post-wire-format-change syntax): Roam-vs-standard-markdown gotchas
(italics are `__text__`; `{{[[TODO]]}}` at block start; H1–H3 only; numbered lists via
`childrenViewType`, not `1.` markers), how to read the ``-tagged output
(`heading`/`childrenViewType`/`refs`/`hiddenChildren`/`truncated` attrs, `((uid))[preview]`
block references), and how to write back without corrupting content (pass only the block content
to `update_block`; keep `((uid))[…]` intact — the server reduces it to `((uid))`;
re-read `truncated="N"` search results via `get_block` before editing). Damage-ranked
structure: the write-back procedure leads as explicit steps with one worked example, and a
short checksum repeats it at the end. Canonical source: `packages/core/src/roam-syntax.ts`
(exported as `ROAM_SYNTAX`). The graph's own `[[roam/agent guidelines]]` govern style and
conventions; the data-integrity rules apply regardless. Also exported:
**`ROAM_SYNTAX_APPEND_ONLY`** — the subset for append-only connections (encrypted graphs:
`get_graph_guidelines` + `append_to_daily_note` only), composed from the same section constants
so it can't drift, with everything referencing tools an append-only agent lacks removed. For the
hosted encrypted-guidelines path to import.
- **Read-tool descriptions teach the wire format**: a shared format note on the 7 read tools that
emit ``-tagged markdown (`get_page`, `get_block`, `get_backlinks`, `search`,
`get_comments`, `roam_query`, `semantic_search`), plus a `truncated="N"` partial-overwrite
warning on `search`/`semantic_search` specifically. (`search_templates` emits plain previews —
no note.)
- **New `skills/roam-syntax/` Agent Skill** (not part of the npm packages — copy it into your
agent's skills directory): SKILL.md with the high-signal gotchas, reading/write-back rules, and
behavioral doctrine, plus references for full syntax, `{{...}}` components, queries, and the
MCP read→edit→write model. A consistency test (`packages/core/test/roam-syntax.test.ts`) pins
the load-bearing invariants shared by the blob and the skill.
- **Schema tightening**: `add_shortcut.index` and `suggest_links.maxResults` now require
non-negative / positive integers (the descriptions always promised counts/positions).
- **README fix**: `search_templates` was wrongly listed among the tools that skip
`#.rm-hide`/`#.rm-private` subtrees — it is exempt (template previews are not filtered), now
stated as an explicit privacy warning in all three READMEs.
- Minor-version bump on purpose: additive feature (new export + new guidelines field), so `^0.9.x`
consumers don't auto-inherit the new-format guidance — the hosted MCP opts in via an explicit
pin bump once its backend emits the new wire format.
## 0.9.2 - 2026-07-29
- **New local-only tool: `call_extension_tool`** (`data.ai.callExtensionTool`) — invokes AI
tools that Roam extensions and roam/js scripts register at runtime. Takes `tool` (the id
exactly as advertised — opaque: qualified `/` for extension-registered
tools, bare `` for roamAlphaAPI-registered ones; never parse or construct it) and
optional `args` (a JSON object matching the tool's advertised `inputSchema`). Registered in
`desktopUiTools`: the hosted backend serves from a peer replica with no channel to a live
client, so this tool must never reach the hosted server. Annotations are worst-case
(destructive, non-idempotent, open-world) since the tool runs arbitrary extension handler
code.
- **All validation is renderer-side; error guidance reaches the model.** Roam meta-validates
schemas at registration and validates the AI's `args` against the tool's `inputSchema`
(draft-07) before the handler runs — roam-tools deliberately ships no validator, keeping
the transport a dumb pipe. The three error classes (unknown tool — lists the currently
available ids; args/schema mismatch — names the violations; handler failure) are written
for model self-correction; their message text reaches the model, though the local client
wraps them as `Server error: ` with code `INTERNAL_ERROR` (they arrive as
Local API 500s). One exception: an app build without the feature returns
`UNKNOWN_ACTION`, which the tool maps to a friendly "update Roam Desktop" message — the
API-version gate can't detect this case (see below).
- Mixed versions: a **pre-0.9.2 roam-tools against a newer Roam Desktop** still forwards
`extensionTools` in `get_graph_guidelines` (the field passes through `...result`) but has
no `call_extension_tool` to invoke them — upgrade roam-tools to invoke.
- **`get_graph_guidelines` now surfaces `extensionTools`** — the local backend's listing of
registered extension AI tools (`{tool, description, scope, extension?, inputSchema?}`),
present only when non-empty and only on the local transport. When present, `nextSteps`
points the agent at `call_extension_tool`. Content-only as before (no `outputSchema`).
- **CLI: JSON flags for non-flat tool params.** The generated commands now parse
object/record/array-typed fields as JSON strings (`roam call-extension-tool --tool x
--args '{"key": "value"}'`), with a clear error on invalid JSON. This also fixes
`datalog-query --inputs`, which previously passed the raw string through and always
failed Zod validation.
- **`EXPECTED_API_VERSION` 1.1.3 → 1.1.5** — the extension-AI-tools feature shipped as Local
API `1.1.5`, a patch revision. Roam's version gate matches major.minor exactly and ignores
patch, so compatibility with older builds is unchanged — which also means the gate **cannot
detect** a desktop build that predates the feature. Older builds return `UNKNOWN_ACTION`
for `data.ai.callExtensionTool` (mapped to the friendly update message above) and simply
omit `extensionTools` from guidelines.
## 0.9.1 - 2026-07-20
- **Two new local-only tools**, each surfacing an existing Roam Local API action. No
API-version change: both actions already ship at `1.1.3`, which matches
`EXPECTED_API_VERSION`, so this is purely a roam-tools-side addition.
- **`suggest_links`** (`data.ai.suggestLinks`) — given a passage of `text`, suggests
existing pages worth linking to, ranked most-plausible first. Suggestion-only: it
does not create links. Optional `maxResults` (default 20).
- **`reload_dev_extensions`** (`depot.reloadDeveloperExtensions`) — reloads all
developer-mode extensions in Roam Desktop (the `C-d C-r` command), returning the
reloaded `{id, name}` list.
- **Both are registered in `desktopUiTools`** (renderer-only Local API actions with no
hosted-MCP counterpart yet, alongside `semantic_search`). MCP tool registration and CLI
command generation are registry-driven, so they surface automatically as the
`suggest_links` / `reload_dev_extensions` MCP tools and `suggest-links` /
`reload-dev-extensions` CLI commands — no per-tool edits to `mcp`/`cli` were needed. Both
are content-only (no `outputSchema`): the returned data is what the agent reads, which
also sidesteps the ChatGPT stale-cache hazard write-schemas carry.
- **Runtime dependency to note:** `reload_dev_extensions` needs a Roam Desktop build from
**2026-07-16** or later (the build that exposed `depot.reloadDeveloperExtensions` on
`roamAlphaAPI`); older builds return `UNKNOWN_ACTION`. `suggest_links` needs a build from
**2026-07-08** or later. This is independent of the npm package version.
## 0.9.0 - 2026-07-15
- **New local-only tool: `semantic_search`** (embeddings) — ranks pages and blocks by
meaning, surfacing conceptually related content that keyword `search` misses. Opt-in: it
requires the user to enable embeddings in Roam and be signed in, and returns an error
telling the agent to fall back to `search` when the graph hasn't enabled it. Registered
as a `desktopUiTool` (needs the renderer's search worker + embeddings index, which the
hosted MCP backend has no counterpart for).
- **New local-only tools: `add_shortcut` / `remove_shortcut`** — add or remove a page in
the graph's left-sidebar Shortcuts (the starred/pinned pages `get_graph_guidelines`
reports as `starredPages`). `add_shortcut` takes an optional `index` to position it.
Registered as `desktopUiTools` for now; promote to `dataTools` once the hosted backend
confirms `data.page.addShortcut` / `removeShortcut`.
- **Fix: `file_upload` MIME detection for non-image files** (#21) — non-image uploads now
resolve the correct content type.
- **Packaging fix: stop publishing the `development` export condition** that pointed at
unshipped `src` (#30). A published `development → ./src/*.ts` condition broke any
downstream consumer whose resolver enables it (Vite/Vitest, Next dev/Turbopack), because
`files` ships only `dist/`. Source resolution now lives in the never-published
`tsconfig.dev.json`. Do **not** re-add a `development` condition to any package's `exports`.
- **`EXPECTED_API_VERSION` 1.1.2 → 1.1.3** — a patch bump. Roam matches major.minor exactly
and ignores patch, so this stays compatible with the same Roam builds `0.8.x` targeted;
the bump just tracks a non-breaking Local API revision. (An intermediate `1.2.0` bump
during development was walked back before release — the published `0.9.0` carries `1.1.3`.)
- **Docs:** documented `((uid))[text]` block-ref previews in the `get_page` /
`get_block` tool descriptions, and the `#.rm-hide` / `#.rm-private` AI-content-hiding tags
in the READMEs.
## 0.8.1 - 2026-07-09
_No runtime change: `core`'s `dist` is byte-identical to `core@0.8.0` once comments are stripped._
- **Publishes `local`, `mcp`, and `cli` at `0.8.1`.** `core` shipped `0.7.5` and `0.8.0`
on its own (for the hosted MCP); the other three stayed at `0.7.4` and never carried
those changes. Upgrading `roam-mcp` / `roam-cli` from `0.7.4` therefore picks up both
the `0.7.5` `nextSteps` copy and the `0.8.0` `graph`-echo behavior at once. `core@0.8.1`
is a comment-only republish so all four packages line up again. The hosted MCP pins
`^0.8.0`, so `core@0.8.1` **does** reach it automatically and unreviewed — safe here
because nothing but comments changed, but the usual patch discipline (`docs/architecture.md` §6)
applies to every `0.8.x` from now on.
- **Neutralized internal infrastructure names in core's source comments** (`operations/pages.ts`,
`types.ts`) and in this changelog, per `docs/architecture.md` §8.1. The `pages.ts` comment
compiled into `dist/` and was therefore shipped inside the published `core@0.7.5`/`0.8.0`
tarballs; `0.8.1` stops it shipping forward.
- **Docs & tests only, otherwise.** Corrected `withGraphField`'s docstring (it injects a
field named `graph`, valued from its `graphLabel` argument — there is no `graphLabel`
key on the wire); refreshed the stale `AccessLevel` and caret-range references in
`docs/architecture.md`; recorded the `publish:all` non-idempotency in `CLAUDE.md`; and
added tests pinning `read-edit-own` (schema + `validLevels` guard) and the echoed
`graph` in a write tool's `structuredContent`.
- **Known gap, tracked in a `TODO(local transport)` at the echo site.** The `0.8.0` echo
suits the hosted MCP but fits the local transport less well: `resolveGraph` auto-selects
when exactly one graph is configured, so a caller that omits `graph` gets the canonical
name back while a later call passing the nickname gets the nickname — one graph, two
labels in one session. Write results also no longer carry the canonical graph they
landed in. Likely fix is an additive canonical `graphName` alongside `graph`.
## 0.8.0 - 2026-06-19
_Minor bump (not a patch): this changes `withGraphField`'s observable output. Per
`docs/architecture.md` §6, a change to the injected `graph` field is a dispatch-contract
change and is not patch-eligible — the caret-pinned hosted MCP must opt into `^0.8.x`
deliberately rather than inherit it automatically._
- **The injected `graph` field now echoes the identifier the caller passed** (the
nickname or name in the tool call's `graph` arg) instead of always the canonical
resolved name. It falls back to the canonical name when no `graph` arg is passed
(single-graph auto-select). This completes the `get_graph_guidelines`
over-orientation fix from 0.7.5: ChatGPT looped because it called the tool by a
nickname (e.g. "work graph"), but the result, which the "do NOT call again for this
graph" directive points at, named only the canonical graph (e.g. "chatgpt-mcp-main"),
so the agent could never tell it had already oriented the graph it knew by that
nickname. Echoing the caller's own identifier lets it match. Applies to every tool
and both transports (local and hosted). The value stays a string (no `outputSchema`
change; write tools' optional `graph` field still validates) and still overwrites any
backend-supplied `graph`, so it is not a spoof vector. No consumer reads the field
programmatically; only the agent does.
- **`roam-cli` inherits this too**, since it dispatches through the same `routeToolCall`
and prints the result body verbatim: `roam get-page --graph work` now reports
`"graph": "work"` rather than the canonical graph name. Note that `0.8.0` was published
for `core` only — the CLI and MCP server pick this change up in `0.8.1`.
## 0.7.5 - 2026-06-14
- **`get_graph_guidelines` `nextSteps` now leads with an explicit "stop orienting"
directive**, to counter ChatGPT's over-orientation loop (observed re-calling
`get_graph_guidelines` ~20× in one turn before doing the task, even on a fresh
connector — so not a cache issue). `nextSteps` now opens with "You now have this
graph's guidelines … Do NOT call get_graph_guidelines again for this graph this
session" before the existing read-the-daily-note guidance, so an agent re-reading
the result mid-loop sees the stop in the response body itself, not only in the
tool description. Copy-only; no schema or behavior change, and it helps every
client. (The hosted MCP's ChatGPT profile separately drops the "before your first
read" trigger from its gentler instructions/description; this core change is the
belt-and-suspenders.)
## 0.7.4 - 2026-06-13
- **Add `read-edit-own` to the `AccessLevel` type** (read + append + edit/delete only the agent's own
content). Additive and runtime-safe: a new union member, with existing values and behavior unchanged,
the local `connect` CLI's hardcoded level list untouched, and `accessLevel` still carried (not enforced)
in core. Shipped as a patch so `^0.7.x` consumers (the caret-pinned hosted MCP) pick it up automatically.
Also accepted by the `GraphConfigSchema` `accessLevel` enum and the `validLevels` token-info status
check. The tier is enforced server-side in the remote/hosted MCP; the local Desktop API tier
is deferred (the local API exposes the full `roamAlphaAPI` surface, not the hosted MCP's closed allowlist).
## 0.7.3 - 2026-06-13
- **Orientation copy: firm "applies to reads too", as the default — with a per-client escape
hatch.** Live testing showed Claude (especially in tool-search mode) skipping
`get_graph_guidelines` on reads — rationalizing them as exempt ("guidelines matter most for
writes") — after 0.7.2 softened the copy to calm ChatGPT's over-orientation loop. ChatGPT and
Claude want opposite copy, so the firm version is now the default and ChatGPT is the exception:
- The `get_graph_guidelines` description and the per-tool `GUIDELINES_NOTE` nudge are firm and
explicitly cover reads ("including simple reads / for reads"; the user's conventions change how
to _interpret and present_ what you read, not just how you write). Dropped 0.7.1's "preferences,
not commands" framing, which had downgraded guidelines to optional.
- New export **`DEFAULT_MCP_INSTRUCTIONS`** — the shared server `instructions` orientation block,
used by the stdio server and as the hosted server's default. The hosted (remote) server
overrides it with a gentler variant for ChatGPT, which over-orients on the "even for reads"
language. Descriptions/instructions only; no behavior change.
## 0.7.2 - 2026-06-13
- **`get_graph_guidelines` description reworked.** Replaced the 0.7.1 "hardening" sentence — which
framed guidelines via the system/developer/user instruction hierarchy and, in practice, sent
high-reasoning agents off on a "where's the developer message?" tangent — with a lighter hint:
guidelines are the user's preferences for _how_ to carry out a request, guidance to respect, not
commands that override what the user actually asked. Also dropped the "your work will likely need
to be redone" pressure. Descriptions only; no behavior change.
- **Softened the server `instructions`.** The orientation block no longer says "do this even for
simple reads / skipping risks violating your setup"; it now says to call `get_graph_guidelines`
**once per graph, then proceed — don't call it again** for that graph. Counters an observed
over-orientation loop (a high-reasoning client re-calling `get_graph_guidelines` dozens of times in
one turn). Mirrored in the hosted MCP server.
## 0.7.1 - 2026-06-13
- **`get_graph_guidelines` description hardened.** Added a sentence clarifying that a graph's
guidelines are user-authored _data_, not instructions to the agent: they express the user's
preferences for how to apply a request and never override system, developer, or user
instructions. Scopes the authority of graph-stored guideline text (relevant for shared graphs)
without changing any behavior.
- **New `core` export: `getDataTools(options)` + `GetDataToolsOptions`.** A factory for `tools/list`
registration. By default it returns the shared `dataTools` array unchanged; with
`omitGuidelinesNoteSuffix: true` it returns a fresh array with the trailing
"call get_graph_guidelines" nudge stripped from each data-tool description (descriptions only —
no behavior, schema, or annotation change). Lets a hosted transport (e.g. ChatGPT) drop the
orientation nudge per-profile while local CLI/MCP keep it. Additive and opt-in: `dataTools`,
`contentTools`, and all existing exports are unchanged.
## 0.7.0 - 2026-06-03
- Added a new tool **`append_to_daily_note`** — a quick-capture tool for adding markdown to a daily
note (todos, notes, summaries). Defaults to today's daily note (also accepts a `date`: `MM-DD-YYYY`
or `today`/`yesterday`/`tomorrow`), creates the page if needed, and optionally appends under an
existing top-level section via `nestUnder`. It is a thin wrapper over the same
`data.block.fromMarkdown` action `create_block` already uses — no new backend action — added for
discoverability and as a narrow, append-only capture surface.
## 0.6.8 - 2026-06-03
- `create_block`'s `dailyNotePage` now accepts the relative words **`today`**, **`yesterday`**, and
**`tomorrow`** (case-insensitive) in addition to `MM-DD-YYYY`. They are resolved to a concrete
`MM-DD-YYYY` **before the value crosses the wire** — against each transport's notion of "today"
(local: the machine clock; hosted: the user's picker timezone) — so the backend and renderer see no
new vocabulary and there is no version coupling. A literal `MM-DD-YYYY` passes through unchanged.
- Added an optional `getCurrentDate?(): string | undefined` to the `RoamActionClient` interface (the
transport's `yyyy-MM-dd` "today"). The local `RoamClient` implements it from the machine clock;
core throws rather than silently falling back to its own (UTC) clock if a relative word arrives
without a base date.
## 0.6.7 - 2026-06-02
- Added **structured tool output on the 8 write tools** (`create_page`, `create_block`,
`add_comment`, `update_block`, `update_page`, `move_block`, `delete_block`,
`delete_page`): they declare an `outputSchema` and return `structuredContent`
alongside the text channel. Schemas are permissive (`.passthrough()`, optional fields)
so backend shape drift doesn't break validation.
- The 9 read tools (and file/nav/standalone) stay **content-only** — `structuredContent`
is emitted only for tools that declare an `outputSchema`. For reads it would just
duplicate the (often large) result already JSON-stringified into the text channel, and
read shapes still evolve — risky since clients (e.g. ChatGPT) validate against a
~1-day-stale cached `tools/list` schema.
- `get_page` / `get_block` now return an explicit `{ found: false }` on a miss
(instead of an empty object that read as a successful empty page/block).
- Hardened `delete_block` / `delete_page` descriptions: deletion is irreversible and
removes all descendants, and for `delete_block` deleting a referenced block
replaces those references elsewhere with the block's text (and comments count as
backrefs); steer inspect-first via `get_block` + `get_backlinks`.
- Graph identity is now carried as a structured `graph` field (canonical graph name),
injected into `structuredContent` + the JSON text body, instead of a `"Roam graph: …"`
text prefix (which read as block content and made a read's JSON non-parseable).
- Fixed `GetBlockResponse.path` type (`string` → `string[]`).
- Raised the `@modelcontextprotocol/sdk` floor to `>=1.26.0 <2.0.0`.
## 0.6.6 - 2026-06-01
- Added MCP tool **annotations** (`readOnlyHint` / `destructiveHint` /
`idempotentHint` / `openWorldHint`) + human titles to every tool, sourced in core
and forwarded by the local and hosted MCP servers. Fixes ChatGPT silently dropping
write tool calls (its safety layer blocks tools that lack these hints).
- Renamed the local MCP server identity to `roam-mcp-local`.
## 0.6.5 - 2026-05-26
- Published all four workspace packages together for the first time:
`@roam-research/roam-tools-core`, `@roam-research/roam-tools-local`,
`@roam-research/roam-mcp`, and `@roam-research/roam-cli`.
- Published `@roam-research/roam-tools-local` as the local Roam Desktop transport
package used internally by MCP and CLI.
- Updated `roam-mcp` and `roam-cli` from their prior public `0.5.1` line to the
new split-package architecture, each with exact `local@0.6.5` sibling pins.
- Verified the local MCP/CLI path after the package split: build, typecheck, lint,
core/local tests, MCP `tools/list`, CLI `list-graphs`, `get-graph-guidelines`,
and `search`.
- Neutralized references to private hosted-MCP infrastructure in public docs and
source comments.
## 0.6.4 - 2026-05-23
- Core-only release.
- Reworded the shared `graph` parameter description.
- Rewrote the `get_graph_guidelines` nudge appended to client tool descriptions.
- Expanded the `get_graph_guidelines` tool description to encourage agents to
fetch graph-specific guidance more reliably.
## 0.6.3 - 2026-05-20
- Core-only release.
- Trimmed the orientation note appended to client tool descriptions to a quieter,
transport-neutral one-liner.
- Added MCP server instructions in the unpublished workspace package to steer
clients through `list_graphs` and `get_graph_guidelines`.
## 0.6.2 - 2026-05-13
- Core-only release.
- Widened `RoamError.code` to accept arbitrary backend-emitted strings while
preserving autocomplete for known `ErrorCodes` values.
- Removed local-client casts that bypassed the stricter error-code type.
- Updated remote-MCP integration notes around the transport-agnostic contract.
## 0.6.1 - 2026-05-09
- Core-only release.
- Added cloud-transport-oriented error code constants:
`MISSING_AUTH`, `INSUFFICIENT_PERMISSION`, `NOT_IMPLEMENTED`,
`GRAPH_UNSUPPORTED`, `ACTION_NOT_AVAILABLE`, and `PEER_NOT_READY`.
## 0.6.0 - 2026-04-25
- Core-only release.
- Split the package architecture into transport-agnostic core plus a local Roam
Desktop transport in the workspace.
- Made core's routing path accept injected graph resolution and client creation,
enabling hosted transports to depend on core without local Desktop code.
## Historical Core-Only Release Window
From `0.6.0` through `0.6.4`, only `@roam-research/roam-tools-core` was published
from the split-package work. During that window, published `roam-mcp` and
`roam-cli` versions remained on `0.5.1`, with exact dependency pins that prevented
them from accidentally picking up `core@0.6.x`.
| Package | Versions on npm | Dependency behavior |
| ----------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
| `roam-mcp` | `0.3.1`, `0.3.2` | Pre-split, all-in-one |
| `roam-mcp` | `0.4.0` to `0.5.1` | Exact one-to-one `core` pin matching the MCP package version |
| `roam-cli` | `0.4.0` to `0.5.1` | Exact one-to-one `core` pin matching the CLI package version |
| `roam-tools-core` | `0.4.0`, `0.4.1`, `0.4.2`, `0.5.0`, `0.5.1`, `0.6.0`, `0.6.1`, `0.6.2`, `0.6.3`, `0.6.4` | Terminal package; hosted transports could install `0.6.x` directly |