Command line interface
lithora puts your workspace — and the confirmation-gated agent — in your terminal and your CI pipeline. Built on the same Python SDK, so there is one HTTP core and one set of semantics.
Install
pipx install lithora-cli # recommended — isolated environment
# or
pip install lithora-cliInstalls the lithora command. Requires Python 3.9 or newer. The package is lithora-cli; the command is lithora. Shell completion is available via lithora --install-completion.
Authenticate
For scripts, CI and anything unattended, use a personal access token. Mint one at Settings → API Tokens — see Authentication for the scope list.
# Mint a token at dashboard.lithora.app/settings -> API Tokens
export LITHORA_TOKEN=lth_pat_your_token_here
lithora whoami
lithora doctor # checks config, connectivity and auth in one shotFor day-to-day interactive use on your own machine you can log in instead:
lithora login --email you@example.com
# Password is prompted; it is never accepted as a flag value.
# The token goes to your OS keychain, or a 600-mode file if no keychain is available.Interactive login cannot complete a 2FA or new-device challenge
lithora login fails with exit code 3 if the account has 2FA enabled or the request comes from an unrecognised device, because neither challenge can be answered from a terminal. That is not a bug to work around — it is the reason to use a token. Set LITHORA_TOKEN and every command works regardless.Resolution order for every setting is flag → environment variable → profile on disk → default. The relevant variables are LITHORA_TOKEN, LITHORA_BASE_URL, LITHORA_PROFILE and LITHORA_OUTPUT. The base URL defaults to https://api.lithora.app, and the CLI prints a loud warning if you point it at a plaintext non-localhost host.
Everyday commands
# Find the team, then create a project inside it
lithora teams list
lithora projects create --name "Q3 Launch" --team <team_id>
# Work items
lithora tasks create --title "Wire up billing" --project <project_id> --priority high
lithora tasks list --project <project_id> --status todo
lithora tasks show <task_id>
lithora tasks status <task_id> in_progress
lithora tasks assign <task_id> --user <user_id>
lithora tasks my # everything assigned to you
lithora tasks delete <task_id> # prompts unless you pass --yesIds are printed by the corresponding list command — run lithora teams list first and copy the team_id. Every group supports --help.
The agent, and the gate
lithora ai "<prompt>" is shorthand for lithora ai chat. If the agent proposes changes it prints the plan and stops — nothing is written until you say yes.
lithora ai "break the autosave issue into a parent task and subtasks"ACTION PLAN (requires confirmation)
Action: 5e2a91c7-… Status: waiting_confirmation
1. + task: Add autosave to the editor [acme/web#418]
- subtask: Persist drafts to localStorage
- subtask: Debounced autosave on change
Summary: Agent will create 1 task + 2 subtasks
Approve? [y]es / [n]o [n]:In CI there is no one to answer the prompt, so the CLI refuses rather than guessing:
# Non-interactive: approve up front, or the run exits 2 rather than hanging.
lithora ai chat "triage last night's CI failures" --yes
# Or review staged plans (overnight triage, CI-failure triage) and approve by id.
lithora ai pending
lithora ai confirm <action_id> --session <session_id>
lithora ai confirm <action_id> --session <session_id> --reject--yes is a standing approval
--yes approves whatever the agent proposes, sight unseen. Use it only where the prompt is narrow and the blast radius is bounded. The safer CI shape is to let autonomous runs stage plans and approve them with lithora ai pending / confirm after a human has read them.Scripting
-o json emits the exact API payload, unmodified. That is the contract to script against — the table renderer is for humans and its columns may change.
lithora tasks list --project <project_id> -o json | jq '.[] | select(.priority=="urgent")'
# -o accepts table (default on a TTY), json, or yaml.
# LITHORA_OUTPUT=json makes it the default for a whole CI job.Exit codes
Exit codes follow Unix conventions so a pipeline can branch on the failure mode rather than grepping stderr.
| Code | Meaning |
|---|---|
| 0 | Success. |
| 1 | Generic failure — including a 5xx or a connectivity problem. |
| 2 | Bad usage, or a plan needed confirmation with no TTY and no --yes. |
| 3 | Not authenticated (401) or forbidden (403). |
| 4 | Not found (404). |
| 5 | Conflict (409). |
| 7 | Rate limited (429) — the SDK already retried. Wait, then re-run. |
| 22 | Invalid input (400 or 422). |
| 130 | Interrupted with Ctrl-C. |
In GitHub Actions
name: Sync release tasks
on:
release:
types: [published]
jobs:
sync:
runs-on: ubuntu-latest
steps:
- run: pipx install lithora-cli
- name: Create the release checklist
env:
LITHORA_TOKEN: ${{ secrets.LITHORA_TOKEN }}
LITHORA_OUTPUT: json
run: |
lithora tasks create \
--title "Post-release checks for ${{ github.event.release.tag_name }}" \
--project "${{ vars.LITHORA_PROJECT_ID }}" \
--priority highProfiles
Profiles work like kubectl contexts: one per account, org or environment. Non-secret state lives in ~/.lithora/config.json (directory 700, file 600); the token itself goes to the OS keychain when one is available.
lithora profile list
lithora profile use staging
lithora profile show
# Per-invocation overrides beat everything:
lithora --profile staging --base-url http://localhost:8000 teams listManaging tokens from the CLI
lithora token list
lithora token create --name ci-release-bot --scope tasks:write --scope projects:read
lithora token revoke <token_id>These need a login session, not a token
403 for a PAT-authenticated caller on create and revoke. Run lithora login first, or manage tokens in the web app.Command groups
| Group | Subcommands |
|---|---|
| lithora login / logout / whoami / doctor | Authenticate, sign out, identify yourself, diagnose. |
| lithora teams | list, show, members, create |
| lithora projects | list, show, create, update, delete |
| lithora tasks | list, my, show, create, status, update, assign, delete |
| lithora work-items | list, graph, cycle-time, pr-status, resolve |
| lithora automations | list, show, create, toggle, execute, history, run-status, export, versions, rollback, templates |
| lithora runners | list, register, manifest, dispatch, jobs, audit, revoke |
| lithora sprints | list, show, create, plan, update, close, summary, velocity |
| lithora webhooks | list, events, show, create, update, delete, logs, clear-logs, stats, rotate-secret, test |
| lithora data | fields, export, import |
| lithora github | status, repos, connect |
| lithora search | query, recent |
| lithora ai | chat (the default), pending, confirm, sessions |
| lithora token | create, list, revoke |
| lithora profile | list, use, show |
Troubleshooting
- Everything exits 3. Run
lithora doctor. It prints the resolved profile, base URL and whether a token was found at all — usually the answer is thatLITHORA_TOKENwas not exported into the shell the command actually ran in. - Requests hit the wrong host.
lithora profile showprints the effective base URL. A staleLITHORA_BASE_URLbeats the profile on disk. - A CI job hangs or exits 2 on an agent command. The plan needed confirmation and there was no TTY. Add
--yes, or split it intoai pendingplus a reviewedai confirm. - Debugging a request.
--debugturns on verbose, credential-redacted request logging.