substantial-brain-cli
v2.1.0
Published
CLI for the brain — upload markdown, list workspaces, grep content, write notes.
Maintainers
Readme
brain
CLI for the brain — upload content, list workspaces, grep for text, write notes, manage your token.
Install
npm install -g substantial-brain-cliRequires Node.js 18+.
Quick start
brain login # save your API token
brain whoami # confirm the token
brain list # list workspaces in your org (alias: brain workspaces)
brain list --visibility shared # only public workspaces
brain grep "stale read" # literal substring search
brain grep "Q1 OKRs" --workspace atlas # restrict to a workspace
brain upload notes.md # upload a single file
brain upload docs/ # upload a folder of supported content
brain upload docs/ --workspace Atlas # assign uploads to a workspace
brain write thought.md --client-key idea-2026-05
# idempotent one-off note
brain delete 0190b8a0-1111-7000-8000-000000000001
# delete a content row (prompts to confirm)Generate an API token at https://substantial-brain.vercel.app/settings/connections.
Commands
brain login
Prompts for an API token, verifies it against https://substantial-brain.vercel.app, and writes credentials to ~/.config/brain/config.json (mode 0600).
Override the config location with BRAIN_CONFIG=/path/to/config.json or XDG_CONFIG_HOME.
brain whoami
Prints the email and organization the saved token belongs to. Useful for confirming you're pointed at the right brain instance.
brain list (aliases: brain workspaces)
Lists every workspace your user can see, ordered by most recent activity. Restricted workspaces require membership; archived workspaces are tagged [archived]; restricted ones are tagged [restricted].
Options:
--visibility <shared|private>— narrow to public (shared) or restricted-and-you're-a-member (private) workspaces. Omit to return both.
brain grep <pattern> [opts]
Literal substring search across content titles and bodies. Distinct from vector retrieval (/api/v1/query and the MCP query_content tool) — use grep when you know the exact phrase the content contains, query when you want conceptually similar hits.
The pattern is treated as a literal string. SQL wildcards (%, _) are escaped automatically — pass the substring as-is, no globbing.
Options:
--workspace <slug>— restrict to content assigned to this workspace.--max <n>— cap results (default50, max200).
brain upload <path...> [opts]
Uploads one or more content files. Directories are walked recursively; any file that looks like text is uploaded, regardless of extension. Binary-looking files are skipped. Hidden files and directories (anything starting with .) are skipped during recursion — pass them explicitly to upload anyway.
The server infers each upload's content kind from the filename and body. Ordinary text/markdown uploads become documents; transcript-shaped uploads such as .vtt, .srt, or files with transcript in the name become transcripts.
Re-uploading an unchanged file is a no-op. Re-uploading a changed file (same filename, same workspace) replaces the previous version.
Options:
--workspace <name|slug>— assign the uploaded content to this workspace. Lookup tries the exact display name first, then falls back to the URL slug (handy for terminal use — no spaces or shell quoting needed). The workspace must already exist; create it in the UI first.
Path identity: the server deduplicates by (workspace, filename). The CLI normalizes typed paths so that docs, docs/README.md, and ./docs/README.md all map to the same upload name (docs/README.md), regardless of invocation style.
brain write <path> [opts]
Creates a single content row from a markdown file. Use this for one-off notes, meeting captures, and decisions you want stored alongside ingested content — for bulk file uploads, use brain upload instead.
Pass --client-key to make the write idempotent: re-running with the same key replaces the body of the previously-written row instead of creating a new one. Same key, same org → same contentId.
Options:
--workspace <slug>— assign the new content to this workspace.--title <s>— display title. Defaults to the file's basename.--kind <document|transcript>— content kind. Defaults todocument.--client-key <s>— stable idempotency key (≤ 128 chars).
sourceType is recorded as manual so the UI can distinguish notes written via this command from connector-ingested content.
brain delete <contentId> [--yes] (alias: brain rm)
Permanently deletes a content row by id (grab the id from brain grep output). Deletion is irreversible and prompts for confirmation before acting.
Authorization is role-scoped, enforced server-side: org owners can delete any content in the org; everyone else can only delete content they uploaded or that came from a connection they own. A row you can see but aren't allowed to delete returns a permission error; a row you can't see returns "not found" (existence isn't leaked). Any direct children are re-rooted (their parent link is cleared) rather than cascade-deleted.
Options:
--yes/-y— skip the confirmation prompt. Required when stdin isn't a TTY (piping / CI), where there's no way to answer interactively.
License
Proprietary. © Substantial.
