skills/clawchives/SKILL.md
The canonical ClawChives©™ agent integration skill. Full API reference for autonomous agents (Lobsters©™) to authenticate, manage bookmarks, folders, and integrate with the ClawChive bookmarking system.
npx skillsauth add acidgreenservers/clawchives clawchives-agent-api©™Install this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
ClawChives©™ is a local-first sovereign bookmarking system that agents can integrate with via HTTP API. This skill document defines every action an agent can take — from authentication to CRUD operations on bookmarks and folders.
Key Principles:
canRead, canWrite, canEdit, canDelete)lb- (Lobster) key hash, issued tokens are api- prefixed| Prefix | Type | Usage | Context |
|--------|------|-------|---------|
| hu- | Human Identity | Secret stored in offline identity file | Login; never sent to server |
| lb- | Lobster (Agent) Key | Secret used to request API tokens | Agent setup; never sent to server |
| api- | API Token | Bearer token for API calls | All authenticated requests |
A human creates an agent key in Settings → Agent Keys.
UI: Settings panel → "+ New Agent Key" button
└─ Human provides a name (e.g., "My Bookmark Crawler")
└─ System generates a 64-character `lb-` key
└─ Human copies the key and gives it to the agent
The agent must hash its lb- key before sending it to the server.
// Pseudocode — your language may vary
async function hashAgentKey(lbKey: string): Promise<string> {
// lbKey format: "lb-aAbBcCdDeEfFgGhH..." (67 chars total)
const encoder = new TextEncoder()
const data = encoder.encode(lbKey)
const hashBuffer = await crypto.subtle.digest("SHA-256", data)
const hashArray = Array.from(new Uint8Array(hashBuffer))
return hashArray.map(b => b.toString(16).padStart(2, "0")).join("")
}
// Output: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" (64 hex chars)
Critical: The raw lb- key is NEVER sent to the server. Only the SHA-256 hash is transmitted.
The agent calls POST /api/auth/token with the hashed key.
POST /api/auth/token
Content-Type: application/json
{
"type": "agent",
"keyHash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
}
Response — 200 OK:
{
"token": "api-aBcDeFgHiJkLmNoPqRsTuVwXyZ123456"
}
Error Responses:
401 Unauthorized — keyHash does not match any registered agent key400 Bad Request — missing or malformed type or keyHash field429 Too Many Requests — rate limit exceeded (max 10 auth attempts per minute per IP)500 Internal — server errorFor all subsequent requests, include the token in the Authorization header:
Authorization: Bearer api-aBcDeFgHiJkLmNoPqRsTuVwXyZ123456
canRead, canWrite, canEdit, canDeleteapi- token by hashing and exchanging its lb- key| Permission | Allows |
|-----------|--------|
| canRead | GET /api/bookmarks, GET /api/bookmarks/:id, GET /api/folders, GET /api/bookmarks/stats, etc. |
| canWrite | POST /api/bookmarks, POST /api/bookmarks/bulk, POST /api/folders |
| canEdit | PUT /api/bookmarks/:id, PUT /api/folders/:id, PATCH /api/bookmarks/:id/star, PATCH /api/bookmarks/:id/archive |
| canDelete | DELETE /api/bookmarks/:id, DELETE /api/bookmarks, DELETE /api/folders/:id, DELETE /api/folders |
If an agent token lacks the required permission for an endpoint, the server returns:
403 Forbidden
Content-Type: application/json
{
"error": "Forbidden",
"message": "This agent key does not have permission to write bookmarks"
}
Retrieve paginated bookmarks with optional search and filtering.
Request:
GET /api/bookmarks?page=1&limit=50&search=lobster&folder=science&tags=crustacean&archived=false
Authorization: Bearer api-aBcDeFgHiJkLmNoPqRsTuVwXyZ123456
Query Parameters:
page (number, optional, default: 1) — pagination page numberlimit (number, optional, default: 50, max: 200) — items per pagesearch (string, optional) — full-text search in title and URLfolder (string, optional) — filter by folder name (exact match)tags (string, optional) — comma-separated tag names (filters to bookmarks with ANY of these tags)archived (boolean, optional) — filter by archive status (true = archived only, false = active only, omit = all)Response — 200 OK:
{
"data": [
{
"id": "bm-uuid-1",
"url": "https://example.com/article",
"title": "Understanding Lobster Communication",
"description": "A deep dive into crustacean linguistics",
"folder": "science",
"tags": ["marine-biology", "behavior"],
"starred": false,
"archived": false,
"createdAt": "2026-03-20T14:30:00Z",
"updatedAt": "2026-03-20T14:30:00Z"
}
],
"meta": {
"page": 1,
"limit": 50,
"total": 127,
"pages": 3
}
}
Permissions Required: canRead
Error Responses:
401 Unauthorized — missing or invalid API token403 Forbidden — token lacks canRead permissionRetrieve a single bookmark by ID.
Request:
GET /api/bookmarks/bm-uuid-1
Authorization: Bearer api-aBcDeFgHiJkLmNoPqRsTuVwXyZ123456
Response — 200 OK:
{
"id": "bm-uuid-1",
"url": "https://example.com/article",
"title": "Understanding Lobster Communication",
"description": "A deep dive into crustacean linguistics",
"folder": "science",
"tags": ["marine-biology", "behavior"],
"starred": false,
"archived": false,
"createdAt": "2026-03-20T14:30:00Z",
"updatedAt": "2026-03-20T14:30:00Z"
}
Permissions Required: canRead
Error Responses:
401 Unauthorized — missing or invalid API token403 Forbidden — token lacks canRead permission404 Not Found — bookmark does not existCreate a single bookmark.
Request:
POST /api/bookmarks
Content-Type: application/json
Authorization: Bearer api-aBcDeFgHiJkLmNoPqRsTuVwXyZ123456
{
"url": "https://example.com/article",
"title": "Understanding Lobster Communication",
"description": "A deep dive into crustacean linguistics",
"folder": "science",
"tags": ["marine-biology", "behavior"]
}
Request Body Schema:
{
url: string // HTTP(S) URL; must be absolute
title: string // 1-255 characters
description?: string // 0-2000 characters (optional)
folder?: string // folder name (optional; created if doesn't exist)
tags?: string[] // array of tag names (optional; max 20 tags)
}
Response — 201 Created:
{
"id": "bm-uuid-1",
"url": "https://example.com/article",
"title": "Understanding Lobster Communication",
"description": "A deep dive into crustacean linguistics",
"folder": "science",
"tags": ["marine-biology", "behavior"],
"starred": false,
"archived": false,
"createdAt": "2026-03-20T14:30:00Z",
"updatedAt": "2026-03-20T14:30:00Z"
}
Permissions Required: canWrite
Error Responses:
400 Bad Request — missing required fields or invalid types401 Unauthorized — missing or invalid API token403 Forbidden — token lacks canWrite permission422 Unprocessable Entity — URL is invalid or duplicate (URL uniqueness enforced per user)429 Too Many Requests — rate limit exceededUpdate an existing bookmark (partial or full).
Request:
PUT /api/bookmarks/bm-uuid-1
Content-Type: application/json
Authorization: Bearer api-aBcDeFgHiJkLmNoPqRsTuVwXyZ123456
{
"title": "Understanding Lobster Communication (Revised)",
"description": "An updated deep dive",
"tags": ["marine-biology", "behavior", "new-tag"]
}
Request Body Schema:
{
url?: string // update URL (optional)
title?: string // update title (optional)
description?: string // update description (optional)
folder?: string // move to folder (optional)
tags?: string[] // replace tags (optional)
}
Response — 200 OK:
{
"id": "bm-uuid-1",
"url": "https://example.com/article",
"title": "Understanding Lobster Communication (Revised)",
"description": "An updated deep dive",
"folder": "science",
"tags": ["marine-biology", "behavior", "new-tag"],
"starred": false,
"archived": false,
"createdAt": "2026-03-20T14:30:00Z",
"updatedAt": "2026-03-25T10:15:00Z"
}
Permissions Required: canEdit
Error Responses:
400 Bad Request — invalid field types or empty body401 Unauthorized — missing or invalid API token403 Forbidden — token lacks canEdit permission404 Not Found — bookmark does not exist422 Unprocessable Entity — URL conflict (duplicate URL)Delete a bookmark by ID.
Request:
DELETE /api/bookmarks/bm-uuid-1
Authorization: Bearer api-aBcDeFgHiJkLmNoPqRsTuVwXyZ123456
Response — 204 No Content
Permissions Required: canDelete
Error Responses:
401 Unauthorized — missing or invalid API token403 Forbidden — token lacks canDelete permission404 Not Found — bookmark does not existDESTRUCTIVE: Delete all bookmarks for the authenticated user. No undo.
Request:
DELETE /api/bookmarks
Authorization: Bearer api-aBcDeFgHiJkLmNoPqRsTuVwXyZ123456
Response — 204 No Content
Permissions Required: canDelete
Error Responses:
401 Unauthorized — missing or invalid API token403 Forbidden — token lacks canDelete permissionImport multiple bookmarks in a single request.
Request:
POST /api/bookmarks/bulk
Content-Type: application/json
Authorization: Bearer api-aBcDeFgHiJkLmNoPqRsTuVwXyZ123456
{
"bookmarks": [
{
"url": "https://example.com/1",
"title": "Article 1",
"folder": "reading",
"tags": ["tech"]
},
{
"url": "https://example.com/2",
"title": "Article 2",
"folder": "reading",
"tags": ["tech", "ai"]
}
]
}
Request Body Schema:
{
bookmarks: Array<{
url: string
title: string
description?: string
folder?: string
tags?: string[]
}> // max 500 bookmarks per request
}
Response — 200 OK:
{
"imported": 2,
"failed": 0,
"results": [
{
"url": "https://example.com/1",
"success": true,
"id": "bm-uuid-1"
},
{
"url": "https://example.com/2",
"success": true,
"id": "bm-uuid-2"
}
]
}
Permissions Required: canWrite
Error Responses:
400 Bad Request — invalid request structure401 Unauthorized — missing or invalid API token403 Forbidden — token lacks canWrite permission422 Unprocessable Entity — partial import with failures (see results array for per-item status)Toggle the starred/favorited status of a bookmark.
Request:
PATCH /api/bookmarks/bm-uuid-1/star
Authorization: Bearer api-aBcDeFgHiJkLmNoPqRsTuVwXyZ123456
Response — 200 OK:
{
"id": "bm-uuid-1",
"starred": true
}
Permissions Required: canEdit
Error Responses:
401 Unauthorized — missing or invalid API token403 Forbidden — token lacks canEdit permission404 Not Found — bookmark does not existToggle the archived status of a bookmark.
Request:
PATCH /api/bookmarks/bm-uuid-1/archive
Authorization: Bearer api-aBcDeFgHiJkLmNoPqRsTuVwXyZ123456
Response — 200 OK:
{
"id": "bm-uuid-1",
"archived": true
}
Permissions Required: canEdit
Error Responses:
401 Unauthorized — missing or invalid API token403 Forbidden — token lacks canEdit permission404 Not Found — bookmark does not existRetrieve aggregated bookmark statistics.
Request:
GET /api/bookmarks/stats
Authorization: Bearer api-aBcDeFgHiJkLmNoPqRsTuVwXyZ123456
Response — 200 OK:
{
"total": 127,
"archived": 12,
"starred": 34,
"untagged": 5,
"byFolder": {
"science": 45,
"reading": 62,
"inbox": 20
},
"byTag": {
"marine-biology": 28,
"ai": 15,
"behavior": 22
}
}
Permissions Required: canRead
Retrieve all tags in use across the user's bookmarks.
Request:
GET /api/bookmarks/tags
Authorization: Bearer api-aBcDeFgHiJkLmNoPqRsTuVwXyZ123456
Response — 200 OK:
{
"tags": [
{ "name": "marine-biology", "count": 28 },
{ "name": "ai", "count": 15 },
{ "name": "behavior", "count": 22 },
{ "name": "research", "count": 18 }
]
}
Permissions Required: canRead
Retrieve all folders.
Request:
GET /api/folders
Authorization: Bearer api-aBcDeFgHiJkLmNoPqRsTuVwXyZ123456
Response — 200 OK:
{
"folders": [
{
"id": "f-uuid-1",
"name": "science",
"createdAt": "2026-03-10T08:00:00Z",
"updatedAt": "2026-03-20T14:30:00Z"
},
{
"id": "f-uuid-2",
"name": "reading",
"createdAt": "2026-03-10T08:00:00Z",
"updatedAt": "2026-03-20T14:30:00Z"
}
]
}
Permissions Required: canRead
Create a new folder.
Request:
POST /api/folders
Content-Type: application/json
Authorization: Bearer api-aBcDeFgHiJkLmNoPqRsTuVwXyZ123456
{
"name": "research-papers"
}
Request Body Schema:
{
name: string // 1-100 characters, unique per user
}
Response — 201 Created:
{
"id": "f-uuid-3",
"name": "research-papers",
"createdAt": "2026-03-25T10:15:00Z",
"updatedAt": "2026-03-25T10:15:00Z"
}
Permissions Required: canWrite
Error Responses:
400 Bad Request — missing or invalid name field401 Unauthorized — missing or invalid API token403 Forbidden — token lacks canWrite permission422 Unprocessable Entity — folder name already exists (uniqueness enforced per user)Update a folder's name.
Request:
PUT /api/folders/f-uuid-3
Content-Type: application/json
Authorization: Bearer api-aBcDeFgHiJkLmNoPqRsTuVwXyZ123456
{
"name": "peer-reviewed-papers"
}
Request Body Schema:
{
name: string // 1-100 characters
}
Response — 200 OK:
{
"id": "f-uuid-3",
"name": "peer-reviewed-papers",
"createdAt": "2026-03-25T10:15:00Z",
"updatedAt": "2026-03-25T11:00:00Z"
}
Permissions Required: canEdit
Error Responses:
400 Bad Request — invalid name field401 Unauthorized — missing or invalid API token403 Forbidden — token lacks canEdit permission404 Not Found — folder does not exist422 Unprocessable Entity — folder name already existsDelete a folder. All bookmarks in the folder are reassigned to "inbox".
Request:
DELETE /api/folders/f-uuid-3
Authorization: Bearer api-aBcDeFgHiJkLmNoPqRsTuVwXyZ123456
Response — 204 No Content
Permissions Required: canDelete
Error Responses:
401 Unauthorized — missing or invalid API token403 Forbidden — token lacks canDelete permission404 Not Found — folder does not existDESTRUCTIVE: Delete all folders. All bookmarks are reassigned to "inbox". No undo.
Request:
DELETE /api/folders
Authorization: Bearer api-aBcDeFgHiJkLmNoPqRsTuVwXyZ123456
Response — 204 No Content
Permissions Required: canDelete
| Code | Meaning | Common Trigger |
|------|---------|----------------|
| 200 OK | Request succeeded | All GET requests, most PUT/PATCH |
| 201 Created | Resource created successfully | POST /api/bookmarks, POST /api/folders |
| 204 No Content | Request succeeded, no body | DELETE requests |
| 400 Bad Request | Malformed request body or missing required fields | Invalid JSON, missing url in POST /api/bookmarks |
| 401 Unauthorized | Missing or invalid API token | Missing Authorization header, expired/invalid token |
| 403 Forbidden | Valid token but lacks required permission | canRead permission missing for GET /api/bookmarks |
| 404 Not Found | Resource does not exist | GET /api/bookmarks/nonexistent-id |
| 422 Unprocessable Entity | Valid request but cannot be processed | Duplicate URL, duplicate folder name |
| 429 Too Many Requests | Rate limit exceeded | >10 auth attempts/min, >500 requests/min |
| 500 Internal Server Error | Server error | Database failure, unexpected exception |
All endpoints are rate-limited. Current limits:
| Endpoint Category | Limit |
|------------------|-------|
| Auth (/api/auth/token) | 10 requests per minute per IP |
| Bookmark read (GET /api/bookmarks*) | 500 requests per minute per token |
| Bookmark write (POST/PUT/DELETE /api/bookmarks*) | 100 requests per minute per token |
| Folder operations (/api/folders*) | 100 requests per minute per token |
Exceeding limits returns 429 Too Many Requests. The response includes a Retry-After header indicating seconds until the limit resets.
All GET list endpoints support:
page (number, optional, default: 1) — page number (1-indexed)limit (number, optional, default: 50, max: 200) — items per pageExample: GET /api/bookmarks?page=2&limit=25 retrieves items 26-50.
GET /api/bookmarks supports:
search (string, optional) — fuzzy search in title and URLfolder (string, optional) — exact folder name matchtags (string, optional) — comma-separated tag names; returns bookmarks with ANY tag in the listarchived (boolean, optional) — filter by archive status"A lobster does not ask permission to take a step forward — but it knows which waters are safe. Know your permissions before you act. A human grants your access; honor that trust by respecting the boundaries they set."
This SKILL.md is the canonical agent integration guide for ClawChives©™. Always fetch this document from /api/skill to stay in sync with the latest API contract.
Maintained by CrustAgent©™
development
# Feature Development Assistant ## Mission Statement You are an expert full-stack developer who builds complete features from concept to implementation using Desktop Commander's file management capabilities. Your role is to analyze existing codebases, design feature architecture, implement all necessary code, and integrate seamlessly with existing systems. ## Important: Multi-Chat Workflow **Feature development requires multiple chat sessions to avoid context limits and manage implementation c
development
# Truthpack Updater Skill ## When to Use Activate this skill whenever: - A new route is added to `server/routes/` - A new environment variable is introduced - The project structure or a feature cluster is modified - Security protocols or auth rules are updated ## Instructions 1. **Audit Phase**: Perform a full-codebase scan (`grep` or `list_dir`) to identify changes since the last truthpack sync. 2. **Atomic Updates**: Update the corresponding JSON file in `.crustagent/vibecheck/truthpack/`:
development
# Truthpack Lookup Skill ## When to Use Activate this skill BEFORE generating any code that: - Creates or modifies API routes - References environment variables - Touches authentication/authorization - Modifies API request/response shapes ## Instructions 1. Read `.crustagent/vibecheck/truthpack/routes.json` for verified API routes 2. Read `.crustagent/vibecheck/truthpack/env.json` for verified environment variables 3. Read `.crustagent/vibecheck/truthpack/auth.json` for verified auth rules 4.
development
# Sovereign Stack Recipes This skill contains verified "Stability Locks" for the ShellPlate codebase. Follow these patterns strictly to maintain CrustCode©™ standards and prevent codebase sprawl. ## 🧪 Testing Patterns (Vitest) - **Vertical Audit**: Colocate as `*.test.ts` next to the implementation. - **Backend**: Use `supertest` for route testing. Mock `authMiddleware.requireAuth` for isolation. - **Frontend**: Use `vitest` + `jsdom`. Mock API calls using `vi.mock`. ## 🎨 UI & Components (T