openwriter 0.5.3 → 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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/skill/SKILL.md +52 -40
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openwriter",
3
- "version": "0.5.3",
3
+ "version": "0.5.4",
4
4
  "description": "The open-source writing surface for AI agents. Markdown-native editor with pending change review — your agent writes, you accept or reject.",
5
5
  "type": "module",
6
6
  "license": "MIT",
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.3"
17
+ version: "0.1.0"
18
18
  repository: https://github.com/travsteward/openwriter
19
19
  license: MIT
20
20
  ---
@@ -27,6 +27,7 @@ You are a writing collaborator. You read documents and make edits **exclusively
27
27
 
28
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
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".
30
31
 
31
32
  ## Setup — Which Path?
32
33
 
@@ -78,29 +79,37 @@ After editing, tell the user:
78
79
 
79
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.
80
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
+
81
90
  ## MCP Tools Reference (32 tools)
82
91
 
83
92
  ### Document Operations
84
93
 
85
- | Tool | Description |
86
- |------|-------------|
87
- | `read_pad` | Read the current document (compact tagged-line format) |
88
- | `write_to_pad` | Apply edits as pending decorations (rewrite, insert, delete) |
89
- | `populate_document` | Populate an empty doc with content (two-step creation flow) |
90
- | `get_pad_status` | Lightweight poll: word count, pending changes, userSignaledReview |
91
- | `get_nodes` | Fetch specific nodes by ID |
92
- | `get_metadata` | Get frontmatter metadata for the active document |
93
- | `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) |
94
103
 
95
104
  ### Document Lifecycle
96
105
 
97
- | Tool | Description |
98
- |------|-------------|
99
- | `list_documents` | List all documents with filename, word count, active status |
100
- | `switch_document` | Switch to a different document by filename |
101
- | `create_document` | Create a new empty document (optional workspace + container placement) |
102
- | `open_file` | Open an existing .md file from any location on disk |
103
- | `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) |
104
113
 
105
114
  ### Import
106
115
 
@@ -132,16 +141,16 @@ After editing, tell the user:
132
141
 
133
142
  ### Agent Marks
134
143
 
135
- | Tool | Description |
136
- |------|-------------|
137
- | `get_agent_marks` | Get inline feedback marks left by the user (optional filename — omit for all docs) |
138
- | `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) |
139
148
 
140
149
  ### Text Operations
141
150
 
142
- | Tool | Description |
143
- |------|-------------|
144
- | `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) |
145
154
 
146
155
  ### Image Generation
147
156
 
@@ -166,7 +175,7 @@ OpenWriter has two distinct modes: **editing** existing documents and **creating
166
175
 
167
176
  For making changes to existing documents — rewrites, insertions, deletions:
168
177
 
169
- - 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`)
170
179
  - Send **3-8 changes per call** for a responsive, streaming feel
171
180
  - Always `read_pad` before editing to get fresh node IDs
172
181
  - Respect `pendingChanges > 0` — wait for the user to accept/reject before sending more
@@ -214,39 +223,42 @@ This eliminates the need for separate `create_workspace`, `create_container`, an
214
223
 
215
224
  ```
216
225
  1. get_pad_status → check pendingChanges and userSignaledReview
217
- 2. read_pad → get full document with node IDs
218
- 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: [...] })
219
228
  4. Wait → user accepts/rejects in browser
220
229
  ```
221
230
 
222
231
  ### Multi-document
223
232
 
224
233
  ```
225
- 1. list_documents → see all docs, find target
226
- 2. read_pad → read active doc (or switch_document first)
227
- 3. write_to_pad({ filename: "Target.md", changes: [...] })
228
- → 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
229
238
  ```
230
239
 
231
240
  ### Creating new content (two-step)
232
241
 
233
242
  ```
234
243
  1. create_document({ title: "My Doc", workspace: "Project", container: "Chapters" })
235
- spinner appears, doc placed in workspace
236
- 2. populate_document({ content: "# ..." }) → content delivered, spinner clears
237
- 3. read_pad get node IDs if further edits needed
238
- 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
239
249
  ```
240
250
 
241
251
  ### Building a workspace (multiple docs)
242
252
 
243
253
  ```
244
254
  1. create_document({ title: "Ch 1", workspace: "My Book", container: "Chapters" })
245
- 2. populate_document({ content: "..." })
255
+ returns docId "ch1docid"
256
+ 2. populate_document({ docId: "ch1docid", content: "..." })
246
257
  3. create_document({ title: "Ch 2", workspace: "My Book", container: "Chapters" })
247
- 4. populate_document({ content: "..." })
258
+ returns docId "ch2docid"
259
+ 4. populate_document({ docId: "ch2docid", content: "..." })
248
260
  5. create_document({ title: "Character Bible", workspace: "My Book", container: "References" })
249
- 6. populate_document({ content: "..." })
261
+ 6. populate_document({ docId: "<from step 5>", content: "..." })
250
262
  7. tag_doc + update_workspace_context → organize and add context
251
263
  ```
252
264
 
@@ -258,8 +270,8 @@ Users can select text in the browser, right-click, and leave an "Agent Mark" —
258
270
 
259
271
  ```
260
272
  1. User says "check my marks" (or you see the hint in read_pad output)
261
- 2. get_agent_marks → all marks across all docs, grouped by filename
262
- 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)
263
275
  4. resolve_agent_marks([ids]) → clears decorations in browser
264
276
  ```
265
277