This file provides guidance to Claude Code when working with code in this repository.
dm is the CLI for Draftmark — a markdown sharing platform for async collaboration between humans and AI agents. It wraps the Draftmark REST API for terminal and agent use.
Part of Rumbo Labs alongside the main Draftmark app.
- Language: TypeScript (ESM)
- CLI framework: Commander.js
- HTTP: Built-in
fetch(Node 18+) - Build:
tsc→dist/ - Package:
draftmarkon npm, binary isdm - Publish: GitHub release triggers
npm publishvia Actions workflow
npm install
npm run build # Compile TypeScript
npm run dev # Watch mode (tsc --watch)
npm link # Install globally for local testing
dm --help # Verify it workssrc/
cli.ts — Entry point, commander setup, all command definitions
api.ts — Fetch wrapper (base URL, auth headers, structured error normalization)
config.ts — Local (.draftmark.json) + global (~/.config/draftmark/config.json) config, resolution helpers
format.ts — ANSI color helpers, label/table/comment formatting, quiet mode
Four files. Keep it that way — no unnecessary abstractions.
- Single entry point: All commands defined in
cli.ts. Don't split into separate command files unless there are 20+ commands. - Config resolution: CLI flag → env var →
.draftmark.json→ global config (~/.config/draftmark/config.json). This order is intentional — flags for one-off overrides, env vars for CI, local config for project context, global for account-wide defaults. - Output convention:
stderrfor status messages (creating, fetching...),stdoutfor data (URLs, JSON, raw markdown). This makes piping work:dm raw | head. The--quietflag suppresses all stderr. - Structured errors: All API errors are normalized to
{ error, code, details }inapi.ts. Commands usefail()helper for consistent exit codes. - Exit codes: 0 ok, 1 general error, 2 auth (401/403), 3 not found (404), 4 conflict (409).
- No dependencies beyond Commander: Use built-in
fetch,fs,path,os,child_process. Don't add axios, chalk, ora, or similar. - ANSI colors: Implemented manually in
format.ts(6 colors + reset). No chalk dependency.
The Draftmark API spec lives in the main repo: draftmark-app/draftmark/openapi.yaml
Base URL: https://draftmark.app/api/v1 (override with --base-url flag or DM_BASE_URL env var).
| Token | Prefix | Use |
|---|---|---|
| Doc API Key | key_ |
Read private docs, list comments |
| Magic Token | (none) | Owner operations (update, close, delete) |
| Account API Key | acct_ |
Account-level operations (create private docs) |
POST /docs— create doc (optionalAuthorizationheader for private docs)GET /docs/:slug— get doc (with?format=rawfor markdown)PATCH /docs/:slug— update content/status (requires magic token)DELETE /docs/:slug— delete (requires magic token)GET /docs/:slug/comments— list commentsPOST /docs/:slug/comments— add commentPOST /docs/:slug/reactions— add reactionPOST /docs/:slug/reviews— mark reviewed
| Command | API Call | Auth |
|---|---|---|
dm create <file> |
POST /docs | api_key (required for --private) |
dm update <file> [slug] |
PATCH /docs/:slug | magic_token |
dm status [slug] |
GET /docs/:slug | api_key |
dm comments [slug] |
GET /docs/:slug/comments | api_key |
dm comment [slug] <body> |
POST /docs/:slug/comments | api_key |
dm react [slug] <emoji> |
POST /docs/:slug/reactions | api_key |
dm review [slug] |
POST /docs/:slug/reviews | api_key |
dm raw [slug] |
GET /docs/:slug?format=raw | api_key |
dm close [slug] |
PATCH /docs/:slug | magic_token |
dm open [slug] |
PATCH /docs/:slug | magic_token |
dm delete [slug] |
DELETE /docs/:slug | magic_token |
dm browse [slug] |
(local) | none |
dm list |
(local) | none |
dm login |
(local) | none |
dm logout |
(local) | none |
dm whoami |
(local) | none |
dm config |
(local) | none |
No test framework yet. To manually test:
# Create a test doc
echo "# Test" | dm create -
# Check it
dm status
dm comments
dm raw
# Clean up
dm delete --confirmCreate a GitHub release — the Actions workflow handles npm publish:
gh release create v0.x.0 --repo draftmark-app/cli --title "v0.x.0" --notes "..."