@cpenned/cli
v0.8.5
Published
Open Brain CLI - a terminal client over the /v1 HTTP API.
Maintainers
Readme
@cpenned/cli
ob - a terminal client for Open Brain. It is a thin, full-coverage wrapper
over the /v1 HTTP API: every command maps
to one endpoint, so the API + guard layer stay the single source of truth. Same
contract as the MCP server, different front end.
Install
The CLI is published to npm. Install it globally and you have the ob bin on
your PATH - no clone or build required:
npm install -g @cpenned/cli
ob --helpFrom source (development)
Building from the monorepo instead:
npm run build -w @cpenned/cli # emits packages/cli/dist/index.js
node packages/cli/dist/index.js --help
npm link -w @cpenned/cli # …or link it onto PATH, then: ob --helpConfigure
ob needs the deployment origin and an obr_ API key. Mint the key from the
web app (Settings → New API key) so the CLI hits the same vault as the web UI
and email. Then save it:
ob config set --url https://<deployment>.convex.site --key obr_...To keep the key out of your shell history, pass --key with no value (a
hidden prompt) or pipe it in with --key -:
ob config set --url https://<deployment>.convex.site --key
pbpaste | ob config set --key -This writes ~/.open-brain/config.json (chmod 600). Resolution order is
environment over file, so you can override per-command or in CI without
touching the file:
| Variable | Meaning |
| --- | --- |
| OPEN_BRAIN_API_URL | Deployment origin (.convex.site on Convex) |
| OPEN_BRAIN_API_KEY | obr_ API key |
| OPEN_BRAIN_CLIENT_TYPE | Stamped as X-Client (default cli) |
Inspect with ob config show (the key is masked) or ob config path.
Usage
Every command prints a calm, human-readable summary. Add --json to any command
to get the raw API payload for piping into jq or scripts. Date flags
(--defer, --deadline, and the deadline bounds on find) take calendar days
(YYYY-MM-DD) or relative shorthand like today/+3d, and the API returns
them as YYYY-MM-DD. The CLI sends your machine's timezone (X-Timezone) on
every request, so relative dates resolve in your zone.
# Views
ob today
ob view upcoming --tz America/New_York
# Tasks
ob task create "Email the landlord" --garden <gardenId> --deadline today --priority high
ob task create "Someday idea" --garden <gardenId> --status backlog
ob task list --garden <gardenId> --status todo in_progress
ob task get <taskId>
ob task update <taskId> --deadline 2026-07-01
ob task done <taskId>
ob task rm <taskId>
ob task tag-add <taskId> --tag <tagId> <tagId>
ob task update <taskId> --tag <tagId> --person <personId> # adds to existing tags/links
ob task update <taskId> --clear deadline projectId # also deferDate, recurrence, habit, event
ob task attachments <taskId>
ob attachment url <attachmentId> --variant thumbnail # short-lived signed download URL
ob task update <taskId> --assignee me # only valid in a garden shared with another user
echo '[{"gardenId":"...","title":"a"},{"gardenId":"...","title":"b"}]' \
| ob task create-batch --partial # failed rows print their error; exits 1 if any failed
# Projects / gardens / tags (same create|list|get|update|rm shape)
ob project create "Q3 launch" --garden <gardenId>
ob project create "Maybe later" --garden <gardenId> --status backlog
ob project list # each row shows progress, e.g. 3/8 done
ob project update <projectId> --clear deadline
ob garden create "Health" --context "fitness, doctor, meds"
ob tag create urgent --color "#c1502e"
# People (personal CRM)
ob person create "Megan" --relationship wife --alias Meg --contact-every 1 --contact-unit week
ob person link <personId> --garden <gardenId> --task <taskId>
ob person link <chrisId> --person "<christinaId>=wife" # connect two people (symmetric)
ob person contacted <personId> # reached out -> restarts the contact clock
ob person contacted <personId> --at -3d # backdate a touch that happened earlier
ob person update <personId> --detail "Kids=Silas, Jude" --clear contactInterval
ob person restore <personId> # undo a person rm (archive)
ob person list
ob person list christina # search name/alias/company/notes
ob task create "Send book rec" --garden <gardenId> --person <personId>
ob task list --person <personId> # tasks linked to a person
# Reading list (only the url is required; title/description are fetched from the page)
ob read create https://example.com/article
ob read list --status unread
ob read status <itemId> read # stamps readAt
ob person link <personId> --reading <itemId>
# Habits
ob habits create "Meditate" --garden <gardenId> --schedule '{"kind":"daily"}'
ob habits create "Gym" --garden <gardenId> --schedule '{"kind":"weekly","times":3}'
ob habits list --garden <gardenId>
ob habits list --cursor <cursor> # next page (the cursor is printed after a full page)
ob person link <personId> --habit <habitId>
ob habits complete <habitId> --day today
ob habits uncomplete <habitId> --day 2026-07-05
ob habits update <habitId> --status paused --clear pausedUntilDay
ob habits archive <habitId>
ob habits unarchive <habitId>
# Strava activities (connect an account first, from the web app's Settings page)
ob strava sync --since-days 30 # backfill/fallback (webhook covers real-time)
ob strava list
ob strava update <activityId> --notes "felt great"
# Calendar (read-only mirror; connect a Google account from the web Settings page)
ob event calendars # list synced calendars
ob event ls --start 2026-07-01 --end 2026-07-31 # ISO or epoch-ms; omit for a default window
ob event sync # pull latest now
# Books (a personal library, distinct from the reading list above)
ob book search "project hail mary" # or --isbn <isbn>
ob book create "Project Hail Mary" --isbn 9780593135204 --status reading
ob book log <bookId> --pages 40 # logs a session, bumps currentPage
ob book status <bookId> read # stamps finishedDay
ob book habit <bookId> --habit <habitId> # link a daily page-goal habit
ob book list --status reading
ob person link <personId> --book <bookId> # "recommended by"
ob settings yearly-book-goal 24 # reading-challenge target
# Reviews
ob review queue # incl. people due for contact
ob review garden <gardenId> # deep review
ob review request <gardenId> # force into the queue
ob review task <taskId> # mark reviewed
# Default review period (applied to new tasks/projects; 2 weeks out of the box)
ob settings # show vault settings
ob settings review --every 1 --unit month # change the default
ob settings review --none # disable it
ob settings timezone America/Denver # set the vault timezone
ob task create "One-off" --garden <gardenId> --no-review # opt one item out
# AI (needs the relevant provider keys configured on the deployment)
ob find authentication bug
ob triage "call dentist, buy milk, draft the Q3 deck"
# Mind Meld (gardens shared with you; sharing itself is set up in the web app)
ob shares # gardens shared with you ("on <origin>" = another Open Brain)
ob shares tasks <shareId> --status todo # that garden's tasks
ob task update <taskId> --assignee me # take a task in a shared garden
ob task update <taskId> --assignee none # unassign it
ob task list --assignee me # your assigned tasks (home vault)
ob profile # your display name/avatar
ob profile --name "Chris P." # set your display name
# API keys (needs the keys:manage scope)
ob key create "ci runner" --scope tasks:write reviews:*
ob key create "shared-reader" --scope tasks:read gardens:read --include-grants
ob key list
ob key rotate <keyId> # rotating the CLI's own key saves the new secret to config
ob key revoke <keyId>Run ob <group> --help (e.g. ob task --help) for the full option list of any
command group.
Agent skills
The CLI ships with the open-brain-cli and open-brain-mcp agent skills so an
assistant - Claude Code, or any other agent that reads ~/.agents/skills - can
drive ob or the MCP tools on your machine. Install them:
ob skills list # what's bundled, and whether it's installed
ob skills install # copy into ~/.agents/skills, link ~/.claude/skills to them
ob skills install --force # overwrite existing copies
ob skills uninstall # remove them from both locationsBy default, skills install into the shared ~/.agents/skills directory and
~/.claude/skills is symlinked to that copy, so Claude Code and any other
agent using the shared directory both pick it up. Pass --dir <path> to
install directly into one specific agent's own skills directory instead (no
shared dir, no symlink), or name skills to act on a subset (e.g.
ob skills install open-brain-mcp). Restart your agent afterwards so it picks
up the new skills. (The MCP package can also install its own skill without this
CLI: npx -y @cpenned/mcp install-skills.)
Develop
npm run typecheck -w @cpenned/cli
npm test -w @cpenned/cli # vitest: client, config, formatThe CLI is intentionally logic-light - it builds request bodies/queries and
renders responses. All validation, the status machine, ownership, and rate
limits are enforced server-side by /v1.
Publishing
MIT-licensed and publish-ready (files, publishConfig, prepublishOnly
build). To cut a release: bump the version, then npm publish -w @cpenned/cli
from the repo root (@cpenned is the owner's npm username scope, so no org is
needed; you must be authenticated as that user). prepublishOnly runs the build
(bundle skills + tsc) first.
