exponential-cli
v1.22.0
Published
CLI to interact with Exponential productivity app - pull actions for LLM consumption
Maintainers
Readme
Exponential CLI
CLI tool to interact with the Exponential productivity app. Pull actions, projects, and workspaces from your Exponential account for use with LLMs and automation.
Installation
npm install -g exponential-cliOr run directly with npx:
npx exponential-cli --helpQuick Start
1. Generate an API Token
- Log into Exponential
- Navigate to
/settings/api-keys - Create a new API key with type "JWT"
- Copy the generated token
2. Configure the CLI
exponential auth login --token <your-jwt-token> --api-url https://www.exponential.im3. Verify Authentication
exponential auth whoamiCommands
Authentication
# Login with token
exponential auth login --token <jwt> --api-url <url>
# Check authentication status
exponential auth whoami
exponential auth status
# Logout
exponential auth logoutActions
# List all active actions
exponential actions list
# List actions for a specific project
exponential actions list --project <project-id>
# List actions with a specific kanban status
exponential actions list --status IN_PROGRESS
# Create an action
exponential actions create -n "Task name" -d "Description" -p <project-id> --priority "1st Priority"
# Update an action
exponential actions update --id <action-id> --kanban DONE
exponential actions update --id <action-id> -n "New name" --priority "2nd Priority" --due 2026-03-15
# Set the do-date (when you plan to work on it). This is what `today` partitions on,
# and it takes precedence over --due.
exponential actions update --id <action-id> --scheduled-start 2026-08-05T09:00
exponential actions update --id <action-id> --scheduled-start null # clear it
# What's actually on your plate: overdue + today + inbox
exponential actions today
# Just the actions whose dueDate is today (excludes overdue — see note below)
exponential actions today --due-only
# Get actions in a date range
exponential actions range --start 2024-01-01 --end 2024-01-31
# Get kanban board view
exponential actions kanban --project <project-id>Triaging an overdue pile
A large overdue count is usually not a large number of missed commitments — it's
a few bulk writes (a generated project plan, an import) that stamped every row
with one identical timestamp. actions overdue separates the two:
exponential actions overdueOverdue: 43
21 of these were bulk-created — stamped with one identical timestamp,
so almost certainly never individually due.
17 actions stamped 2026-07-25T08:29:55.483Z (10d overdue)
Projects: Entity Money Map, Net Worth Baseline, Tax Reserve System, …
Amnesty: exponential actions defer --ids cmqcgvtlh…,cmqcgvtnn…,…
19 individually dated — real debt, oldest first.
12d Send out the job description for the data engineering role [Hiring]Then pick a disposition:
# Amnesty: clear the dates, back to the project backlog untimed.
# For work that was never really due on the date it carries.
exponential actions defer --ids id1,id2,id3
# Reschedule: still due, just later.
exponential actions reschedule --ids id1,id2 --to today
exponential actions reschedule --ids id1,id2 --to 2026-08-10Note on
actions today: as of v1.9.0 this returns the same overdue/today/inbox partition the/todaypage renders, rather than a due-date-only list. The old behaviour silently omitted the overdue pile — it would report 6 actions while 43 sat overdue. Pass--due-onlyfor the previous output shape.
Goals and OKRs
Objectives are goals; they carry integer ids. Their key results carry CUIDs
and live under goals kr.
# List a workspace's objectives, or the annual → quarterly cascade
exponential goals list --workspace clear --period Q3-2026
exponential goals list --workspace clear --tree
exponential goals list --all-workspaces # "what am I neglecting" is cross-workspace
exponential goals list --project <cuid> # objectives (yours) linked to a project
exponential goals get 46
exponential goals create --workspace clear --title "Ship the CLI" --period Q3-2026
# Close a quarter. set-status/close write ONLY the status column.
exponential goals close --id 46 # → completed
exponential goals set-status --id 46 --status on-hold
# Everything else is a partial update: fields you don't pass are left alone,
# and "none" is how you clear one.
exponential goals update --id 46 --title "Ship the CLI, properly"
exponential goals update --id 46 --workspace none # make it personal
exponential goals reparent --id 47 --parent 46 # or --parent none
exponential goals delete --id 46 # refuses if it has key results
exponential goals periods
exponential goals stats --workspace clear --period Q3-2026
# The quarter at a glance: objectives with their key results nested
exponential okrs list --workspace clearKey results:
exponential goals kr list --goal 46
exponential goals kr list --workspace clear --status at-risk
exponential goals kr create --goal 46 --title "Weekly active agents" --target 500 --unit count
exponential goals kr checkin --id <cuid> --value 120 --note "post-launch bump"
exponential goals kr update --id <cuid> --target 600
exponential goals kr link --id <cuid> --feature <feature-cuid> # or --project <cuid>
exponential goals kr unlink --id <cuid> --project <cuid>
exponential goals kr delete --id <cuid>Meetings and meeting notes
# List meetings you can see (owned, attended, or shared via project/workspace)
exponential meetings list
exponential meetings list --workspace clear --mine
exponential meetings list --archived
# One meeting: details, participants, summary and notes
exponential meetings get <cuid>
exponential meetings get <cuid> --transcript # also print the raw transcript
# Create a meeting manually (a transcript is required by the API)
exponential meetings create -t "Weekly sync" --transcript-file ./sync.txt --notes "Decisions: ..."
cat transcript.txt | exponential meetings create -t "Standup" --transcript-file - --date 2026-08-25T14:00
# Update — only the fields you pass are written
exponential meetings update --id <cuid> -t "Renamed" --summary "Recap ..."
# Permanently delete meetings you own. More than one id requires --force; ids that
# aren't yours are skipped and reported (and the exit code is non-zero).
exponential meetings delete <cuid>
exponential meetings delete --force <cuid> <cuid> <cuid>
# DANGER: deletes every meeting the filter matches — permanently. Filter deliberately.
exponential meetings list --mine --archived | jq -r '.meetings[] | select(.archivedAt != null) | .id' | exponential meetings delete --force --ids-file -
# Meeting notes: read raw Markdown (safe to redirect), replace, or append a block
exponential meetings notes get <cuid> > notes.md # --json for a {id, notes} envelope
exponential meetings notes set <cuid> --file notes.md # or inline, or --file - for stdin
exponential meetings notes append <cuid> "Follow-up: ship it" # separated by a blank lineDecisions and open questions
The workspace Decision Log. An open question is a decision with --status OPEN —
there is no separate model, and that is exactly what a meeting's "Open questions"
panel shows.
# The log, and the open questions in it
exponential decisions list --workspace clear
exponential decisions list --workspace clear --status OPEN
exponential decisions list --workspace clear --product clear --search "retention"
exponential decisions list --workspace clear --number 3 --limit 20 # D-0003; cap the page
# Everything logged from one meeting — both panels (drafts too, if you can edit it)
exponential decisions list --meeting <meeting-cuid>
# One decision in full: body, evidence, deciders, chain and links.
# Anything that takes a decision accepts its D-number or its id.
exponential decisions get D-0006
exponential decisions get <cuid>
# Log a decision from a meeting. Markdown bodies come from a file or stdin.
exponential decisions create -s "Ship the importer behind a flag" \
--status ACCEPTED --source AGENT --meeting <meeting-cuid> \
--body-file ./decision.md \
--decider "Ada Lovelace <[email protected]>" --decider "Grace Hopper"
# Log an open question from the same meeting
exponential decisions create -s "Do we backfill historical rows?" \
--status OPEN --meeting <meeting-cuid>
# Log an open question on a feature: created and linked in one call
exponential decisions create -s "Which store backs the cache?" \
--status OPEN --feature <feature-cuid> --body-file ./options.md --json
# Bulk: a JSON array of decisions in one call — the flags become its defaults.
# This is the path for filing everything that came out of one meeting.
exponential decisions create --from-file ./decisions.json --meeting <meeting-cuid> --source AGENT
jq '.decisions' notes.json | exponential decisions create --from-file - --meeting <meeting-cuid>
# Answer an open question; supersede or deprecate a decision (`set-status` is an alias)
exponential decisions status D-0006 --status ACCEPTED
exponential decisions status D-0006 --status SUPERSEDED --superseded-by <cuid>
# Record what implements it (unlink takes the LINK id, from `decisions get`)
exponential decisions link D-0006 --ticket <ticket-cuid>
exponential decisions unlink --link <link-cuid>
# Let the server propose decisions from a meeting, then review them
exponential decisions draft extract --meeting <meeting-cuid>
exponential decisions draft confirm <cuid>
exponential decisions draft reject <cuid>
# Confirm a draft and accept it in one command, as the signed-in person.
# Agent keys can't confirm. Works on already-confirmed decisions too.
# A draft's D-number can't be looked up until it's confirmed, so pass its id.
exponential decisions confirm <cuid> --status ACCEPTED--from-file takes a JSON array (or {"decisions": [...]}), each entry a create
input — statement is the only required field:
[
{
"statement": "Ship the importer behind a flag",
"body": "## Context\n...\n## Consequences\n...",
"status": "ACCEPTED",
"deciders": ["Ada Lovelace <[email protected]>"],
"evidence": [{ "turnIndex": 41, "speaker": "Ada", "text": "Behind a flag then." }]
},
{ "statement": "Do we backfill historical rows?", "status": "OPEN" }
]Entries are written one at a time so a failure names the entry that failed; the exit code is non-zero unless every entry landed.
Scope flags on the command (--meeting, --workspace, --product, --source,
--status, --decided-at, --decider, ...) apply to every entry that doesn't
set its own. --body, --body-file and --evidence-file are per-decision
content rather than shared scope, so they are refused alongside --from-file —
put body and evidence on the entries. An entry carrying a field this format
doesn't know (a typo'd "decider", say) is rejected rather than filed without
it.
Evidence is checked. Turns are quotes from the meeting's transcript: the
turnIndex must resolve and the words must be that turn's (compared loosely for
case, punctuation and whitespace). Quotes that don't match are dropped by the
server without complaint, and speaker/startTime are replaced with the
transcript's own values — so evidence always needs --meeting, and the CLI
refuses it without one rather than letting the server reject the whole call.
Statuses: OPEN (an open question) · PROPOSED · ACCEPTED · SUPERSEDED ·
DEPRECATED. The last two are reached with decisions status, never at creation.
Projects
# List all projects
exponential projects list
# List projects in a workspace (slug or CUID)
exponential projects list --workspace clear
# One project, with its objectives, key results, DRI and actions
exponential projects get <cuid|slug>
# Partial update — unnamed fields are preserved
exponential projects update --id <cuid> --name "KR support" --status COMPLETED
exponential projects update --id <cuid> --product none
# Refuses while the project still has actions or OKR links
exponential projects delete --id <cuid> [--force]Products, tickets, epics and user stories
# Products take a slug or a CUID
exponential products list --workspace clear
exponential products update <slug|cuid> --workspace clear --description "..." [--fun-ticket-ids|--no-fun-ticket-ids]
# Deleting a product cascades its features, tickets and epics: refuses unless --force
exponential products delete <slug|cuid> --workspace clear [--force]
# Free-text ticket search within a product: title, shortId or ticket number
exponential tickets search "login redirect" --product <slug|cuid> --workspace clear [--limit 50]
# Epics: their tickets and actions are unlinked, not deleted
exponential epics delete --id <cuid>
# A feature's native user stories
exponential features stories list --feature <cuid>
exponential features stories update --id <story-cuid> --i-want "..." [--scope <scope-cuid>|null]
exponential features stories rm --id <story-cuid>Workspaces
# List all workspaces
exponential workspaces list
# Set default workspace
exponential workspaces set-default <workspace-slug>
# List members — each row carries the mention markup for that person
exponential workspaces members --search andiComments and @mentions
Features, tickets, actions, pages, and goals all take comments:
exponential features comment list --feature <feature-id>
exponential features comment add --feature <feature-id> -m "Looks good to me"
exponential tickets comment add --id <ticket-id> -m "Reproduced on staging"
exponential pages comment add --page <page-id> -m "Needs a diagram"
exponential goals comment add --goal 42 -m "On track for Q3"A mention is the literal markup @[Display Name](userId) — writing plain @andi
notifies nobody. --mention expands a name, email, or user id into that markup:
exponential features comment add --feature <feature-id> \
--mention andi \
-m "@andi — could you sanity-check the scope here?"@andi is substituted in place so the sentence still reads. If the body has no
matching @handle the mention is prepended instead. --mention is repeatable,
and an ambiguous name is an error rather than a guess.
Editing and deleting are author-only. Find ids with exponential search "<text>".
Runner — run your Assistant on this machine
An Assistant whose executor is My machine (local runner) (Settings → AI assistant → Delegation) is never run on the server. Instead this CLI claims its queued runs with the Assistant's runner key and works them with Claude Code under your own login, in a directory you choose. The server never names the directory or the CLI.
# 1. Log in with the Assistant's runner key (Settings → AI assistant → New runner key)
exponential auth login --token exp_agent_... --api-url https://www.exponential.im
# 2. Choose where the spawned session works (local config only)
exponential runner config set cwd ~/code/my-project
# 3. Work queued runs until stopped, or claim one and exit
exponential runner start
exponential runner start --once --runner-id laptop
# 4. Keep it running as a user service (launchd on macOS, systemd --user on Linux)
exponential runner install --dry-run # show the service file first
exponential runner install
exponential runner uninstallFor each run the runner spawns claude -p <brief> --output-format stream-json --append-system-prompt <persona> with a per-run Exponential MCP server (npx -y exponential-mcp serve, exponential-mcp ≥ 0.8) so the session can report_progress, ask_owner and finish_run; the stream is parsed into the run's transcript, heartbeats keep the run alive, and the run is finished with the session's summary. Calls to the app retry with backoff and are idempotent, so a laptop going to sleep loses nothing. Add tools the session may use without asking with runner config set allowed-tools "Read,Bash(git:*)".
Output Formats
JSON Output (for LLMs and automation)
By default, output is JSON when piped. Force JSON output:
exponential actions list --jsonExample output:
{
"actions": [
{
"id": "clx123abc",
"name": "Fix authentication bug",
"description": "JWT tokens expiring too early",
"status": "ACTIVE",
"priority": "1st Priority",
"kanbanStatus": "IN_PROGRESS",
"dueDate": "2024-01-15T00:00:00.000Z",
"project": {
"id": "clx456def",
"name": "Exponential App"
},
"assignees": []
}
],
"total": 1,
"filters": {}
}Pretty Output (for humans)
Force human-readable output:
exponential actions list --prettyWorks with OpenClaw
If you use OpenClaw, install the Exponential skill to give your AI agent full access to actions, projects, and kanban boards:
npx clawhub install exponentialYour agent can then create tasks, update statuses, and manage projects through natural conversation.
LLM Integration
Python Example
import subprocess
import json
def get_exponential_actions(project_id=None):
cmd = ['exponential', 'actions', 'list', '--json']
if project_id:
cmd.extend(['--project', project_id])
result = subprocess.run(cmd, capture_output=True, text=True)
return json.loads(result.stdout)
# Get all actions
actions = get_exponential_actions()
# Get actions for a specific project
project_actions = get_exponential_actions('clx456def')Shell Example
# Get actions and pipe to jq
exponential actions list --json | jq '.actions[] | {name, priority, status: .kanbanStatus}'
# Count actions by status
exponential actions kanban --json | jq '.actions | group_by(.kanbanStatus) | map({status: .[0].kanbanStatus, count: length})'Claude/LLM Prompt Example
I have access to the Exponential CLI. Here are my current actions:
$(exponential actions list --json)
Based on these actions, what should I work on next considering priority and due dates?Configuration
Configuration is stored in:
- macOS:
~/Library/Preferences/exponential-cli-nodejs/config.json - Linux:
~/.config/exponential-cli-nodejs/config.json - Windows:
%APPDATA%\exponential-cli-nodejs\config.json
Kanban Status Values
BACKLOG- In backlogTODO- Ready to work onIN_PROGRESS- Currently being worked onIN_REVIEW- In reviewDONE- CompletedCANCELLED- Cancelled
Priority Values
1st Prioritythrough5th PriorityQuick- Quick tasksScheduled- Scheduled tasksErrand- ErrandsRemember- Things to rememberWatch- Items to watchSomeday Maybe- Future possibilities
Development
# Install dependencies
npm install
# Build
npm run build
# Run locally
node bin/exponential.js --help
# Link for local testing
npm linkLicense
MIT
