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.
- package/package.json +1 -1
- 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
|
+
"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.
|
|
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
|
|
100
|
-
| `switch_document` | Switch to a different document by
|
|
101
|
-
| `create_document` | Create a new empty document
|
|
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
|
|
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 — **`
|
|
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({
|
|
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
|
|
226
|
-
2. read_pad → read active doc (or switch_document first)
|
|
227
|
-
3. write_to_pad({
|
|
228
|
-
→ edits go to the
|
|
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
|
-
→
|
|
236
|
-
2. populate_document({ content: "# ..." })
|
|
237
|
-
|
|
238
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|