The open-source writing surface for AI agents. Markdown-native editor with pending change review — your agent writes, you accept or reject.
OpenWriter exposes 7 tools with mixed quality. Tool names follow verb_noun convention (claim_enrichment, mark_enriched, compile_manuscript, export_manuscript, inspect_blog_repo, publish_blog_post, create_editing_draft). Descriptions are present but verbose and domain-specific, making them harder for LLMs to parse. Most tools lack explicit input schemas in the visible code, schemas are inferred from parameter documentation rather than formally declared JSON Schema. Parameters have descriptions but lack type constraints (enums, min/max). Error handling is minimal; no recovery guidance. Security concerns: publish_blog_post is IRREVERSIBLE with no confirmation step. Output schemas are not documented. Composition is reasonable (each tool has one primary action), but parameter relationships are underdocumented.
Claim up to 12 stale documents after 5 seconds idle. Returns full canonical content, title, revision, claimToken and expiresAt for each. Summarize this snapshot, not read_pad. Claims are exclusive for 5 minutes and recover after restart. Empty docs means stop; retryAfterMs indicates settling/leased work. Complete with mark_enriched including each claimToken. Workspace opt-outs and archives are excluded.
Compile a manuscript doc (content_type "manuscript") into the assembled master book and report its structure + any problems — WITHOUT writing a file. Resolves every `doc:` pointer in the manifest, concatenates the canonical (accepted) bodies in manifest order under their chapter headings, namespaces footnotes, then returns: title, per-chapter word counts, chapter count, total word count, and warnings. Warnings flag unresolved pointers — a beat that points at a missing/renamed/archived doc — so this is the build-time feedback loop: run it to confirm the binding resolves and see how each chapter is sizing up. Pass includeMarkdown:true to also return the full assembled markdown (large for a real book). Target the manifest by docId (8-char hex).
Compatibility entry for creating a Revision variant beneath its source document. Copies accepted text, preserves the writing format and source references, and saves an original version. Manuscripts compile into editable document revisions. Returns identity and outline, not the full body. Does not change the active document. Use normal editing tools and Focus mode.
Compile a manuscript doc and WRITE the rendered book to a file: epub (KDP-ready ebook), docx (Word), html (single styled file), or md (the raw assembled master markdown). Same compile + render path as the in-app preview, so the file matches what you see there. Writes to ~/.openwriter/exports/<title>.<ext> by default (or an explicit outputPath) and returns the absolute path plus any compile warnings. EPUB/HTML ship print-light (e-readers handle their own dark mode). Target the manifest by docId (8-char hex).
No formal JSON Schema definitions visible in source code. Parameter types, constraints (min/max/enum), and output schemas are documented in prose descriptions rather than machine-parseable JSON Schema. This forces LLMs to infer valid values from text, increasing hallucination risk.
publish_blog_post is marked IRREVERSIBLE but has no confirmation step, dry-run mode, or recovery tool. An agent can publish to a live blog without user approval, risking unintended public content.
Descriptions are verbose (100 - 200+ chars) and domain-specific (e.g., 'claimToken', 'logline', 'manifest'). LLMs struggle to extract intent from dense prose. Descriptions should be 50 - 150 chars, action-focused, and include WHEN to use the tool.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 54 | 2026-07-28+ | v2 |
Clone or update a GitHub blog repo, walk its structure, sample frontmatters, infer the site's publishing contract (frontmatter schema, defaults, field mappings, image field), and return a BlogSite config ready to pass to publish_blog_post. Detects the content directory, analyzes post samples, and auto-detects the public site URL (CNAME, wrangler route, or GitHub Pages). Returns the inferred config and any warnings.
Complete claimed enrichment in one batch. First call claim_enrichment and summarize its exact content. Requires each claimToken; expired, changed, archived or opted-out documents are not marked fresh. Successful writes atomically stamp baselines and logline, preserve status, clear staleness and retire legacy domain/concepts/docRole fields. Never submit an unclaimed summary.
Publish a document as a blog post to a GitHub-hosted blog. Requires a BlogSite config (from inspect_blog_repo or manual setup). Writes the post markdown + frontmatter to the content directory, commits and pushes to the configured branch, and returns the commit hash and public post URL. Frontmatter is auto-generated from the document's metadata and the site's schema.
No output schemas documented. LLMs cannot plan downstream calls or extract required fields (e.g., does compile_manuscript return chapter_ids for further processing?). Responses are unstructured.
Parameter relationships underdocumented. claim_enrichment and mark_enriched form a two-step workflow (claim → mark), but the dependency is not explicit in parameter descriptions. LLMs may call mark_enriched without claiming first.