npm package: @filipc77/cowrite
Description: Live commenting and inline editing plugin for coding agent sessions
Latest version: 0.6.23

# Cowrite

Live commenting and inline editing plugin for coding agent sessions. Select text to comment, click to edit — your coding agent receives all changes in real time via MCP.

**The problem:** When working with AI coding agents, there's no way to give inline, contextual feedback on specific parts of a file while the agent is working. You either interrupt with a chat message (losing spatial context) or wait until the agent is done.

The solution: Cowrite opens a live preview of any text file where you can select text and leave comments. The comments propagate directly into the agent ssss — so the agent can act on your feedback immediately. Any agent that supports MCP can use Cowrite's tools (get_pending_comments, resolve_comment, etc.). Claude Code users get additional integration: auto-installed hooks that surface comments on every prompt, and /review + /watch skills. The preview also supports inline editing: click any block to edit it, insert new blocks with the + button, and undo with Cmd+Z — all changes are saved to disk instantly.

## How it works

```
Browser (Preview UI)          Node.js Process              Claude Code
┌──────────────────┐     ┌──────────────────────┐     ┌────────────────────┐
│ File preview     │     │  HTTP + WebSocket    │     │                    │
│ Text selection   │◄───►│  server (port 3377)  │     │  MCP tools:        │
│ Comment creation │     │                      │     │                    │
│ Comment sidebar  │     │  ┌────────────────┐  │     │  get_pending       │
└──────────────────┘     │  │ CommentStore   │  │     │  resolve           │
                         │  │ (shared memory)│  │     │  reply             │
                         │  └───────┬────────┘  │     │  propose_change    │
                         │          │           │     │  get_annotated     │
                         │          │           │     │  wait_for_comment  │
                         │  ┌───────▼────────┐  │     │                    │
                         │  │ MCP Server     │◄─╋────►│                    │
                         │  │ (stdio)        │  │     │                    │
                         │  └────────────────┘  │     └────────────────────┘
                         │                      │
                         │  File Watcher        │
                         └──────────────────────┘
```

A single Node.js process runs both the HTTP/WebSocket preview server and the MCP stdio server, sharing one in-memory comment store. Inline edits from the browser are applied to the file on disk via WebSocket, and the file watcher propagates changes back to all connected clients.

## Quick Start

### 1. Install and set up

```bash
npm install -g @filipc77/cowrite
cowrite init
```

The global install gives you the `cowrite` CLI. `cowrite init` installs hooks and skills into your project's `.claude/` directory so they're available when Claude Code starts.

### 2. Add Cowrite as an MCP server in Claude Code

**For this project only** (recommended):

```bash
claude mcp add cowrite -- npx -y @filipc77/cowrite@latest serve
```

**For all projects** (user-level):

```bash
claude mcp add -s user cowrite -- npx -y @filipc77/cowrite@latest serve
```

### 3. Open the preview

The browser opens automatically when a new Claude Code session starts. The default port is `3377`, but if it's in use (e.g. running cowrite in multiple repos), it automatically picks the next available port.

If you need to reopen the browser later (e.g. you closed the tab), run from any terminal:

```bash
cowrite open
```

Pick a file and you'll see a live preview.

### 4. Comment or edit

**Commenting:** Select any text in the preview. A **Comment** button appears — click it to open the comment form. Your text selection stays intact, so you can still copy-paste normally.

**Editing:** Click any block in the preview to edit it inline (contentEditable for text, textarea for code blocks and tables). Press the **+** button between blocks to insert a new block from a searchable menu. Press **Cmd+Enter** to save your edit, **Escape** to cancel, or **Cmd+Z** to undo (up to 50 levels).

### 5. The agent picks up your comments

Comments are handled in two ways:

- **On your next message** — Whenever you send any message to the agent, pending comments are automatically included. The agent sees them, makes the changes, and resolves them. You don't need to mention the comments — just send any message (even about something else) and the agent will handle them.
- **`/watch` (hands-free)** — Type `/watch` once per session to start a background watcher. The agent handles comments as soon as they arrive, without you needing to send a message. Your main conversation stays free for other work.

### 6. Auto-installed integration

On first run, `cowrite serve` installs into your project's `.claude/` directory:
- **Hooks** (`UserPromptSubmit` + `Stop`) — surface pending comments to the agent automatically
- **Skills** (`/review` + `/watch`) — manual and background comment handling
- Hooks are merged into existing `settings.json` — your other settings are preserved

## CLI Reference

```
cowrite init                         Install hooks and skills into .claude/ (run once per project)
cowrite serve [--port N]             Start MCP server + preview server (browse any file)
cowrite preview <file> [--port N]    Open browser preview for a specific file + start MCP server
cowrite open [--port N]              Open the browser to an already-running preview server

Options:
  --port, -p    Port for preview server (default: 3377)
  --no-open     Don't auto-open the browser on serve/preview startup
  --help, -h    Show help
```

`init` installs Claude Code hooks and skills before your first session. `serve` and `preview` auto-open the browser on startup — use `--no-open` to disable. `open` reopens the browser from any terminal (reads the port from `.cowrite-port`).

## MCP Tools

### `get_preview_url`

Returns the URL of the live preview server. Ask the agent for this to know which port to open.

### `get_pending_comments`

Returns unresolved comments from the live preview.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `file` | string | — | Filter by file path (optional) |
| `status` | `"pending"` \| `"resolved"` \| `"all"` | `"pending"` | Filter by status |

### `resolve_comment`

Marks a comment as addressed. The browser UI updates to show the resolved state.

| Parameter | Type | Description |
|-----------|------|-------------|
| `commentId` | string | The comment ID to resolve |

### `reply_to_comment`

Sends a reply from the agent, visible in the browser comment sidebar.

| Parameter | Type | Description |
|-----------|------|-------------|
| `commentId` | string | The comment ID to reply to |
| `reply` | string | The reply text |

### `propose_change`

Proposes a text replacement for a comment's selected text. The user sees a diff in the browser with Apply/Reject buttons. Preferred over direct file edits when responding to comments on selected text.

| Parameter | Type | Description |
|-----------|------|-------------|
| `commentId` | string | The comment ID to propose a change for |
| `newText` | string | The replacement text |
| `explanation` | string | Explanation of the change |

### `get_file_with_annotations`

Returns the file content with inline comment markers at the positions where comments are anchored:

```
Hello world, this is a test. [COMMENT #a1b2c3d4: "Should be uppercase"]
```

| Parameter | Type | Description |
|-----------|------|-------------|
| `file` | string | File path to annotate |

### `wait_for_comment`

Blocks until a new comment is posted in the live preview, then returns it. If pending comments already exist, returns the latest one immediately. Times out after 30 seconds by default.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `timeout` | number | 30 | Max seconds to wait |

## MCP Resources

| URI | Description |
|-----|-------------|
| `cowrite://comments` | Live list of all comments (subscribable) |

## Features

- **Live file watching** — Edit the file externally and the preview updates instantly. Comments re-anchor to their selected text automatically.
- **Markdown rendering** — `.md` files are rendered as formatted HTML. All other text files display with syntax-preserved plain text.
- **Persistent comments** — Comments are saved to `.cowrite-comments.json` in the project directory and survive restarts.
- **Offset-based anchoring** — Comments are anchored by character offset and selected text, not line numbers. When the file changes, Cowrite searches for the selected text near the original offset to re-anchor.
- **Agent replies** — The agent can reply to comments, and replies appear in the browser sidebar in real time.
- **Auto-port selection** — If port 3377 is in use (e.g. running cowrite in multiple repos), it automatically tries the next port (3378, 3379, etc.).
- **Auto-installed hooks** — `cowrite serve` automatically installs Claude Code `UserPromptSubmit` and `Stop` hooks that surface pending comments to the agent. Merges with existing settings.
- **Inline editing** — click any block to edit directly (contentEditable for text, textarea for code/tables)
- **Block insertion** — + button between blocks, searchable menu
- **Undo** — Cmd+Z or header button, up to 50 levels, persisted across file switches

## Skills

Cowrite ships with two built-in Claude Code skills (auto-installed to `.claude/skills/`):

- **`/review`** — Check all pending comments, make changes, reply in the preview, and resolve each one.
- **`/watch`** — Start a background watcher that handles comments as they arrive. Does **not** block the main conversation — you can keep working normally while comments are handled in the background.

## How Comments Flow

1. You select text in the browser and submit a comment
2. The browser sends a WebSocket message to the server
3. The server adds the comment to the shared `CommentStore`
4. The store persists to `.cowrite-comments.json` and emits events
5. The agent receives the comment via one of:
   - The `Stop` hook catching it when the agent finishes its current task
   - The `UserPromptSubmit` hook injecting it on the next user message
   - `wait_for_comment` returning immediately (if `/watch` is active)
   - The agent calling `get_pending_comments` directly
6. The agent responds — either calling `propose_change` (user sees a diff with Apply/Reject) or `reply_to_comment` + `resolve_comment`
7. The browser receives the update via WebSocket and shows the reply and resolved state

## How Edits Flow

1. You click a block in the browser preview to enter edit mode
2. After editing, press Cmd+Enter to save — the browser sends an `edit_apply` message via WebSocket
3. The server writes the updated content to the file on disk
4. The file watcher detects the change and broadcasts the new content to all connected clients
5. Comments re-anchor to their selected text in the updated file

## Development

```bash
git clone https://github.com/your-username/cowrite.git
cd cowrite
npm install

# Run in dev mode (uses tsx for live TS execution)
npm run dev -- preview ./README.md

# Run tests
npm test

# Type-check
npm run lint

# Build for distribution
npm run build
```

## Project Structure

```
cowrite/
├── bin/cowrite.ts              # CLI entry point (auto-installs hooks)
├── src/
│   ├── types.ts                # TypeScript interfaces
│   ├── comment-store.ts        # In-memory comment store with persistence
│   ├── mcp-server.ts           # MCP tools and resources
│   ├── preview-server.ts       # HTTP + WebSocket server
│   ├── file-watcher.ts         # File change detection
│   └── utils.ts                # Markdown rendering, annotation
├── ui/
│   ├── index.html              # Browser preview app
│   ├── styles.css              # Dark theme styles
│   └── client.js               # Selection handling, WebSocket client
├── .claude/
│   ├── skills/                 # Agent skills (review, watch)
│   └── hooks/                  # Auto-installed comment injection hook
└── test/                       # Vitest tests
```

## License

MIT