openwriter 0.5.2 → 0.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/skill/SKILL.md CHANGED
@@ -14,7 +14,7 @@ description: |
14
14
  Requires: OpenWriter MCP server configured. Browser UI at localhost:5050.
15
15
  metadata:
16
16
  author: travsteward
17
- version: "0.5.2"
17
+ version: "0.1.0"
18
18
  repository: https://github.com/travsteward/openwriter
19
19
  license: MIT
20
20
  ---
@@ -23,6 +23,12 @@ license: MIT
23
23
 
24
24
  You are a writing collaborator. You read documents and make edits **exclusively via MCP tools**. Edits appear as pending decorations (colored highlights) in the user's browser that they accept or reject.
25
25
 
26
+ ## FIRM RULES
27
+
28
+ 1. **ALWAYS write content in the editor, never in the terminal.** OpenWriter is a collaborative writing surface. All content — drafts, rewrites, brainstorms, outlines — goes on the pad via `write_to_pad` or `populate_document`. Dumping content into the chat/terminal is bad UX: it's hard to read, ugly, and the user can't accept/reject or iterate on it. If you're generating text the user will read, it goes in the editor.
29
+ 2. **The terminal is for discussion only.** Use chat messages to explain your edits, ask questions, discuss direction, or summarize what you changed. Never use it as the writing surface.
30
+ 3. **Name every document.** When you encounter a generically named doc ("Quote Tweet", "Article", "Untitled", etc.), rename it based on its content before proceeding. Titles are the human scanning layer — a sidebar full of "Quote Tweet" is useless. Use `rename_item` with the docId. Short, descriptive titles: "Venezuela Proxy States QT", "Feature Blindness Article".
31
+
26
32
  ## Setup — Which Path?
27
33
 
28
34
  Check whether the `openwriter` MCP tools are available (e.g. `read_pad`, `write_to_pad`). This determines setup state:
@@ -73,29 +79,37 @@ After editing, tell the user:
73
79
 
74
80
  **Note:** You cannot run `claude mcp add` from inside a session (nested session error). That's why we edit the JSON directly when configuring from within Claude Code. Also, `claude mcp add` appends to the end — always verify the entry is first after adding.
75
81
 
82
+ ## Document Identity: Titles vs DocIds
83
+
84
+ Every document has an immutable **docId** (8-char hex, e.g. `a1b2c3d4`) in its YAML frontmatter. Titles are for human communication and agent reasoning. DocIds are for agent action.
85
+
86
+ - `list_documents` and `read_pad` always show both title and docId
87
+ - All doc-targeting tools take `docId` as their parameter (not filename)
88
+ - Two documents can have the same title — the docId disambiguates
89
+
76
90
  ## MCP Tools Reference (32 tools)
77
91
 
78
92
  ### Document Operations
79
93
 
80
- | Tool | Description |
81
- |------|-------------|
82
- | `read_pad` | Read the current document (compact tagged-line format) |
83
- | `write_to_pad` | Apply edits as pending decorations (rewrite, insert, delete) |
84
- | `populate_document` | Populate an empty doc with content (two-step creation flow) |
85
- | `get_pad_status` | Lightweight poll: word count, pending changes, userSignaledReview |
86
- | `get_nodes` | Fetch specific nodes by ID |
87
- | `get_metadata` | Get frontmatter metadata for the active document |
88
- | `set_metadata` | Update frontmatter metadata (merge, set key to null to remove) |
94
+ | Tool | Key Params | Description |
95
+ |------|-----------|-------------|
96
+ | `read_pad` | — | Read the current document (compact tagged-line format with `id:` in header) |
97
+ | `write_to_pad` | `docId`, `changes` | Apply edits as pending decorations (rewrite, insert, delete) |
98
+ | `populate_document` | `docId?`, `content` | Populate an empty doc with content (two-step creation flow) |
99
+ | `get_pad_status` | — | Lightweight poll: word count, pending changes, userSignaledReview |
100
+ | `get_nodes` | `nodeIds` | Fetch specific nodes by ID |
101
+ | `get_metadata` | — | Get frontmatter metadata for the active document |
102
+ | `set_metadata` | `metadata` | Update frontmatter metadata (merge, set key to null to remove) |
89
103
 
90
104
  ### Document Lifecycle
91
105
 
92
- | Tool | Description |
93
- |------|-------------|
94
- | `list_documents` | List all documents with filename, word count, active status |
95
- | `switch_document` | Switch to a different document by filename |
96
- | `create_document` | Create a new empty document (optional workspace + container placement) |
97
- | `open_file` | Open an existing .md file from any location on disk |
98
- | `delete_document` | Delete a document file (moves to OS trash, recoverable) |
106
+ | Tool | Key Params | Description |
107
+ |------|-----------|-------------|
108
+ | `list_documents` | — | List all documents with title, docId, word count, active status |
109
+ | `switch_document` | `docId` | Switch to a different document by docId |
110
+ | `create_document` | `title?`, ... | Create a new empty document response includes docId |
111
+ | `open_file` | `path` | Open an existing .md file from any location on disk |
112
+ | `delete_document` | `docId` | Delete a document file (moves to OS trash, recoverable) |
99
113
 
100
114
  ### Import
101
115
 
@@ -127,16 +141,16 @@ After editing, tell the user:
127
141
 
128
142
  ### Agent Marks
129
143
 
130
- | Tool | Description |
131
- |------|-------------|
132
- | `get_agent_marks` | Get inline feedback marks left by the user (optional filename — omit for all docs) |
133
- | `resolve_agent_marks` | Remove marks after addressing feedback (pass mark IDs) |
144
+ | Tool | Key Params | Description |
145
+ |------|-----------|-------------|
146
+ | `get_agent_marks` | `docId?` | Get inline feedback marks left by the user (optional docId — omit for all docs) |
147
+ | `resolve_agent_marks` | `mark_ids` | Remove marks after addressing feedback (pass mark IDs) |
134
148
 
135
149
  ### Text Operations
136
150
 
137
- | Tool | Description |
138
- |------|-------------|
139
- | `edit_text` | Fine-grained text edits within a node (find/replace, add/remove marks) |
151
+ | Tool | Key Params | Description |
152
+ |------|-----------|-------------|
153
+ | `edit_text` | `docId`, `nodeId`, `edits` | Fine-grained text edits within a node (find/replace, add/remove marks) |
140
154
 
141
155
  ### Image Generation
142
156
 
@@ -161,7 +175,7 @@ OpenWriter has two distinct modes: **editing** existing documents and **creating
161
175
 
162
176
  For making changes to existing documents — rewrites, insertions, deletions:
163
177
 
164
- - Use `write_to_pad` for all edits — **`filename` is required**
178
+ - Use `write_to_pad` for all edits — **`docId` is required** (8-char hex from `list_documents` or `read_pad`)
165
179
  - Send **3-8 changes per call** for a responsive, streaming feel
166
180
  - Always `read_pad` before editing to get fresh node IDs
167
181
  - Respect `pendingChanges > 0` — wait for the user to accept/reject before sending more
@@ -209,39 +223,42 @@ This eliminates the need for separate `create_workspace`, `create_container`, an
209
223
 
210
224
  ```
211
225
  1. get_pad_status → check pendingChanges and userSignaledReview
212
- 2. read_pad → get full document with node IDs
213
- 3. write_to_pad({ filename: "Doc.md", changes: [...] })
226
+ 2. read_pad → get full document with node IDs + docId
227
+ 3. write_to_pad({ docId: "a1b2c3d4", changes: [...] })
214
228
  4. Wait → user accepts/rejects in browser
215
229
  ```
216
230
 
217
231
  ### Multi-document
218
232
 
219
233
  ```
220
- 1. list_documents → see all docs, find target
221
- 2. read_pad → read active doc (or switch_document first)
222
- 3. write_to_pad({ filename: "Target.md", changes: [...] })
223
- → edits go to the named file, no view switch needed
234
+ 1. list_documents → see all docs with title + [docId]
235
+ 2. read_pad → read active doc (or switch_document({ docId }) first)
236
+ 3. write_to_pad({ docId: "e5f6a7b8", changes: [...] })
237
+ → edits go to the identified doc, no view switch needed
224
238
  ```
225
239
 
226
240
  ### Creating new content (two-step)
227
241
 
228
242
  ```
229
243
  1. create_document({ title: "My Doc", workspace: "Project", container: "Chapters" })
230
- spinner appears, doc placed in workspace
231
- 2. populate_document({ content: "# ..." }) → content delivered, spinner clears
232
- 3. read_pad get node IDs if further edits needed
233
- 4. write_to_pad refine with edits
244
+ returns docId "a1b2c3d4", spinner appears
245
+ 2. populate_document({ docId: "a1b2c3d4", content: "# ..." })
246
+ content delivered, spinner clears
247
+ 3. read_pad get node IDs + docId if further edits needed
248
+ 4. write_to_pad({ docId: "a1b2c3d4", ... }) → refine with edits
234
249
  ```
235
250
 
236
251
  ### Building a workspace (multiple docs)
237
252
 
238
253
  ```
239
254
  1. create_document({ title: "Ch 1", workspace: "My Book", container: "Chapters" })
240
- 2. populate_document({ content: "..." })
255
+ returns docId "ch1docid"
256
+ 2. populate_document({ docId: "ch1docid", content: "..." })
241
257
  3. create_document({ title: "Ch 2", workspace: "My Book", container: "Chapters" })
242
- 4. populate_document({ content: "..." })
258
+ returns docId "ch2docid"
259
+ 4. populate_document({ docId: "ch2docid", content: "..." })
243
260
  5. create_document({ title: "Character Bible", workspace: "My Book", container: "References" })
244
- 6. populate_document({ content: "..." })
261
+ 6. populate_document({ docId: "<from step 5>", content: "..." })
245
262
  7. tag_doc + update_workspace_context → organize and add context
246
263
  ```
247
264
 
@@ -253,8 +270,8 @@ Users can select text in the browser, right-click, and leave an "Agent Mark" —
253
270
 
254
271
  ```
255
272
  1. User says "check my marks" (or you see the hint in read_pad output)
256
- 2. get_agent_marks → all marks across all docs, grouped by filename
257
- 3. Address each mark → rewrite, insert, delete via write_to_pad
273
+ 2. get_agent_marks → all marks across all docs, grouped by document
274
+ 3. Address each mark → rewrite, insert, delete via write_to_pad (use docId)
258
275
  4. resolve_agent_marks([ids]) → clears decorations in browser
259
276
  ```
260
277
 
@@ -357,6 +374,8 @@ Users set their X handle by clicking the avatar circle in the compose area. The
357
374
 
358
375
  **MCP tools not available** — The OpenWriter MCP server isn't configured yet. Follow the [setup instructions](#mcp-tools-are-not-available-skill-first-install) above. After adding the MCP config, the user must restart their Claude Code session.
359
376
 
377
+ **Browser dies mid-session** — The MCP stdio pipe can break during context compaction or session resets. The HTTP server survives (crash guards), but MCP tools stop working. Tell the user: **run `/mcp` to reconnect.** The new process enters client mode and proxies MCP calls to the surviving HTTP server. The browser will auto-reconnect.
378
+
360
379
  **Port 5050 busy** — Another OpenWriter instance owns the port. New sessions auto-enter client mode (proxying via HTTP) — tools still work. No action needed.
361
380
 
362
381
  **Edits don't appear** — Stale node IDs. Always `read_pad` before `write_to_pad` to get fresh IDs.
@@ -365,4 +384,6 @@ Users set their X handle by clicking the avatar circle in the compose area. The
365
384
 
366
385
  **Server not starting** — Ensure `openwriter` works from your terminal (`npm install -g openwriter` first). If on Windows and the global command isn't found, the MCP config may need `"command": "cmd"` with `"args": ["/c", "openwriter", "--no-open"]`.
367
386
 
387
+ **After code changes** — Run `npm run build` in `packages/openwriter`, then `/mcp` to restart with the new build.
388
+
368
389
  **Slow to load / loads last** — MCP servers load sequentially in config order. Move `openwriter` to the first position in `mcpServers` in `~/.claude.json`. See setup instructions above.