UNPKG

@nakedved/ano

Version:

Claude Code plugin for collaborative annotation and review

409 lines (319 loc) • 13.8 kB
### 🚨🚨 Beta release out now!! 🚨🚨 # Ano **Collaborative annotation and review for Claude Code** Ano enables teams to annotate, review, and approve Claude-generated plans and markdown files before execution. It integrates with Claude Code via MCP and hooks, creating a human-in-the-loop workflow for AI-assisted development. ## Features - **Inline Annotations** - Add comments to specific lines with types: `concern`, `question`, `suggestion`, `blocker` - **Approval Gates** - Require N approvals before Claude can proceed (via hooks) - **Title & Role-Based Authorization** - Require approval from specific roles (e.g., "Tech Lead", "Security") - **Team Management** - Configure team members, roles, and approval requirements - **Web Viewer** - Visual interface with real-time updates, keyboard shortcuts, and inline editing - **Activity Feed** - Track all annotation and approval changes chronologically - **Version Diff** - Compare changes between versions, see what was added/removed/resolved - **Shareable URLs** - Deep links to specific annotations or lines - **Export** - Export annotated files as standalone HTML or copy for Claude - **Multi-file Support** - Review multiple files in a single session - **Claude Integration** - Claude can read and respond to annotations via MCP - **Git-Friendly** - All data stored in sidecar JSON files alongside your code ## Quick Start ```bash # Install globally npm install -g @vedpawar/ano # Add an annotation ano annotate plan.md:15 "Is this approach safe?" --type concern # List annotations ano list plan.md # Approve a file ano lgtm plan.md # Check approval status (for hooks) ano check plan.md # Start web viewer ano serve plan.md # Start web viewer with multiple files ano serve plan.md README.md design.md ``` ## Installation ### From npm (Recommended) ```bash npm install -g @vedpawar/ano ``` ### From source ```bash git clone https://github.com/vedpawar2254/Ano.git cd Ano npm install npm run build:all npm link ``` ## CLI Commands ### Annotations | Command | Description | |---------|-------------| | `ano annotate <file>:<line> "msg"` | Add annotation to a specific line | | `ano annotate <file>:<start>-<end> "msg"` | Add annotation spanning multiple lines | | `ano list <file>` | List all annotations for a file | | `ano resolve <file> <id>` | Mark annotation as resolved | | `ano reply <file> <id> "msg"` | Add threaded reply | | `ano delete <file> <id>` | Delete an annotation | | `ano sync <file>` | Sync annotation positions after file changes | ### Quick Shortcuts | Command | Description | |---------|-------------| | `ano lgtm <file>` | Quick approve ("Looks good to me") | | `ano shipit <file>` | Strong approve ("Ship it!") | | `ano nit <file>:<line> "msg"` | Minor nitpick (won't block) | | `ano block <file>:<line> "msg"` | Add blocker (will block) | | `ano q <file>:<line> "msg"` | Quick question | ### Approvals & Checks | Command | Description | |---------|-------------| | `ano approve <file>` | Add approval with optional title | | `ano approve <file> --title "Tech Lead"` | Approve with a title (for role-based gates) | | `ano check <file>` | Verify approval requirements (exit 0/1) | | `ano check <file> --required 2` | Require specific number of approvals | | `ano check <file> --require-title "Tech Lead"` | Require approval from specific title | | `ano check <file> --require-role lead` | Require approval from specific team role | | `ano check <file> --soft` | Warn but don't block | | `ano check <file> --override --reason "msg"` | Bypass with audit trail | | `ano check <file> --json` | Output result as JSON | ### Version Comparison | Command | Description | |---------|-------------| | `ano diff <file>` | Show changes from previous version | | `ano diff <file> --json` | Output diff as JSON | ### Team Management | Command | Description | |---------|-------------| | `ano team init [name]` | Initialize team configuration | | `ano team add <email>` | Add team member | | `ano team remove <email>` | Remove team member | | `ano team list` | List team members and requirements | | `ano team roles` | Show available roles | ### Web Viewer | Command | Description | |---------|-------------| | `ano serve <file>` | Start web viewer on localhost:3000 | | `ano serve <files...>` | View multiple files with tab switching | | `ano serve <file> --port 8080` | Use custom port | | `ano serve <file> --no-open` | Don't open browser automatically | ## Web Viewer Features The web viewer provides a rich interface for reviewing annotated files: ### Keyboard Shortcuts | Key | Action | |-----|--------| | `j` / `↓` | Next annotation | | `k` / `↑` | Previous annotation | | `r` | Resolve selected annotation | | `Shift+D` | Delete selected annotation | | `a` | Add annotation at selected line | | `/` | Focus search | | `?` | Show keyboard shortcuts help | | `Esc` | Close modal / deselect | ### Views - **Annotations** - List and filter annotations by status (all/open/blockers) - **Activity** - Chronological feed of all annotation and approval changes - **Changes** - Diff view showing what changed since page load (added, removed, resolved) ### Sharing - **Copy link to view** - Deep link to current annotation/line selection - **Copy for Claude** - Formatted markdown summary of open annotations - **Export HTML** - Standalone HTML file with all annotations embedded ### Inline Editing Double-click any line to edit it directly. Changes are saved automatically. ### Text Selection Select text across lines to add annotations to specific ranges. ### Real-time Updates The viewer uses Server-Sent Events (SSE) to automatically refresh when files or annotations change. ## Claude Code Integration ### MCP Server Add to your Claude Code settings (`.claude/settings.json`): ```json { "mcpServers": { "ano": { "command": "node", "args": ["/path/to/ano/dist/mcp/server.js"] } } } ``` Available MCP tools: - `read_annotations` - Read annotations for a file - `add_annotation` - Add a new annotation - `resolve_annotation` - Mark as resolved - `approve_file` - Add approval ### Approval Gate Hook Block Claude from executing plans without approval: ```json { "hooks": { "PreToolUse": [ { "matcher": "Write", "command": "ano check PLAN.md --quiet" } ] } } ``` #### Advanced Hook Examples Require Tech Lead approval: ```json { "command": "ano check PLAN.md --require-title 'Tech Lead' --quiet" } ``` Require 2 approvals from team leads: ```json { "command": "ano check PLAN.md --required 2 --require-role lead --quiet" } ``` Soft gate (warn but don't block): ```json { "command": "ano check PLAN.md --soft --quiet" } ``` Exit codes: - `0` = Approved, Claude proceeds - `1` = Not approved, Claude blocked Override logs are written to `.ano-overrides.log` for audit trails. ## Team Configuration Team config is stored in `.ano/config.json`: ```json { "version": "1.0", "projectName": "My Project", "members": [ { "name": "Alice", "email": "alice@example.com", "role": "lead" }, { "name": "Bob", "email": "bob@example.com", "role": "reviewer" } ], "roles": { "lead": { "canOverride": true, "weight": 2 }, "reviewer": { "canOverride": false, "weight": 1 } }, "requirements": { "minApprovals": 2, "requiredRoles": ["lead"], "requiredTitles": ["Tech Lead"] } } ``` ### Requirements Options | Field | Description | |-------|-------------| | `minApprovals` | Minimum number of approvals required | | `minWeight` | Minimum total weight of approvals (based on role weights) | | `requiredRoles` | Roles that must approve (matches team member roles) | | `requiredTitles` | Titles that must approve (matches approval titles) | Team membership is **advisory only** - anyone can approve, but `ano check` shows who is/isn't in the team. ## How It Works ### Annotation Storage Annotations are stored in sidecar files alongside your source: - `plan.md` → `plan.md.annotations.json` This keeps annotations git-tracked and version-controlled with your code. ### Content Anchoring When files change, annotations can become misaligned. Ano uses **content anchoring** to relocate annotations: 1. Stores surrounding context (2 lines before/after) 2. Stores content hash for change detection 3. On file change, searches for matching context 4. Uses fuzzy matching (Levenshtein distance) for tolerance Run `ano sync <file>` to update positions after major edits. ### Shareable URLs URLs encode the current view state: - `#annotation=<id>` - Link to specific annotation - `#line=<number>` - Link to specific line - `#file=<path>` - Link to specific file (multi-file mode) Example: `http://localhost:3000/#annotation=abc123` ### Authentication **No login required.** Ano uses your git identity: ```bash git config user.name # Your name git config user.email # Your email ``` This makes Ano trust-based (same as git commits). ## Workflow Example ``` ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” │ 1. Claude generates plan.md │ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ │ ā–¼ ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” │ 2. Team reviews (via CLI or web viewer) │ │ ano serve plan.md │ │ ano block plan.md:15 "Security concern" │ │ ano q plan.md:30 "Why this approach?" │ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ │ ā–¼ ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” │ 3. Address feedback │ │ ano resolve plan.md <blocker-id> │ │ (Claude can read annotations via MCP and respond) │ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ │ ā–¼ ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” │ 4. Approve │ │ ano approve plan.md --title "Tech Lead" │ │ ano lgtm plan.md │ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ │ ā–¼ ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” │ 5. Execute │ │ User: "Execute the plan" │ │ Hook: ano check plan.md → exit 0 │ │ Claude: *proceeds with implementation* │ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ ``` ## Project Structure ``` ano/ ā”œā”€ā”€ src/ │ ā”œā”€ā”€ core/ # Core data operations │ │ ā”œā”€ā”€ annotations.ts # CRUD for annotations │ │ ā”œā”€ā”€ anchoring.ts # Position tracking │ │ ā”œā”€ā”€ config.ts # User identity (git) │ │ ā”œā”€ā”€ team.ts # Team configuration │ │ └── types.ts # TypeScript interfaces │ ā”œā”€ā”€ cli/ # CLI commands │ │ ā”œā”€ā”€ index.ts # Entry point │ │ └── commands/ # Individual commands │ │ ā”œā”€ā”€ annotate.ts │ │ ā”œā”€ā”€ approve.ts │ │ ā”œā”€ā”€ check.ts │ │ ā”œā”€ā”€ diff.ts │ │ ā”œā”€ā”€ list.ts │ │ ā”œā”€ā”€ serve.ts │ │ └── ... │ └── mcp/ # MCP server for Claude │ └── server.ts ā”œā”€ā”€ web/ # Svelte 5 web viewer │ ā”œā”€ā”€ src/ │ │ ā”œā”€ā”€ App.svelte │ │ └── lib/ │ │ ā”œā”€ā”€ FileViewer.svelte │ │ ā”œā”€ā”€ Sidebar.svelte │ │ ā”œā”€ā”€ AnnotationCard.svelte │ │ ā”œā”€ā”€ ActivityFeed.svelte │ │ ā”œā”€ā”€ DiffView.svelte │ │ └── ... │ └── dist/ # Built assets ā”œā”€ā”€ hooks/ # Example hook configurations │ └── README.md └── .ano/ # Team config (per-project) └── config.json ``` ## Annotation Types | Type | Purpose | Blocks Execution | |------|---------|------------------| | `blocker` | Must resolve before proceeding | Yes | | `concern` | Risk or issue identified | No | | `question` | Clarification needed | No | | `suggestion` | Improvement idea | No | ## License MIT ## Contributing Contributions welcome! Please open an issue or PR.