@kanera/cli
v2.2.0
Published
Kanera command-line interface for terminals and AI agents
Maintainers
Readme
kanera CLI
Manage Kanera work from a terminal, or from any AI agent that can run shell commands.
Install
Requires Node 22 or newer. The package has no dependencies.
npm install --global @kanera/cliAn agent can inspect the complete command surface without installing anything globally:
npx -y @kanera/cli commandsAuthenticate
kanera auth login # sign in through your browser
kanera whoami # who am I, and what may this credential do?auth login uses the OAuth device flow, the same way Claude or Codex connects. It prints a link
and a short code, opens the link in your browser, and finishes when you approve the code there.
It works over SSH too: open the link on any device. Pass --no-browser to only print the link.
The CLI stores a short-lived access token and a refresh token, refreshes them automatically, and
appears under Settings → AI agents as "Kanera CLI (your machine)", where you can revoke it.
kanera auth logout revokes it for you.
When an AI agent drives the CLI, name it at sign-in so Kanera labels its work as that agent's:
kanera auth login --agent "Claude Code" # or set KANERA_AGENT_NAMEThe sign-in is then registered as "Claude Code (Kanera CLI on your machine)", which is what the
consent screen, Settings → AI agents, and every comment, card change and run chip show as
"via …". The name is fixed for that sign-in; use a separate --profile per agent on a shared
machine. API keys cannot carry an agent name, because personal-key work is recorded as the user.
Use an API key for CI, cron, or an unattended agent, where nobody can approve a browser sign-in, or when you want a server-enforced read-only credential:
kanera auth login --with-api-key # opens the API-keys page, then prompts for the key
kanera auth login --api-key kanera_u_… # store a key non-interactivelyCreate keys in the web app under Settings → API keys, or in workspace settings for a key
tied to a workspace rather than a person. In CI or an agent sandbox, skip the stored profile and
set KANERA_API_KEY instead.
Self-hosting? A browser sign-in needs your deployment's MCP address, because the sign-in is bound
to it: kanera auth login --mcp-url https://your-kanera.example/mcp (or KANERA_MCP_URL). For an
API key, point at your public API with --url https://api.your-kanera.example during login (it is
saved with the profile) or via KANERA_PUBLIC_API_URL.
Use
kanera commands # everything this CLI can do (works before login)
kanera work # your assignments across every accessible board
kanera card MKT-42 # a card, by key, id, or URL
kanera card done MKT-42 # mark it complete
kanera card block API-12 WEB-40 # API-12 blocks WEB-40 (unblock / relate work the same way)
kanera deps WEB-40 # what blocks WEB-40 and what it holds up, across boards (--boardId <id> maps a board)
kanera comment MKT-42 "Shipped."
kanera separator create <boardId> <listId> "This week" --color blue
kanera separator move <separatorId> <listId> --anchor.side before --anchor.item.type card --anchor.item.id <cardId>
kanera workspace create "Marketing" --templateId marketing # bootstrap a workspace (org admin)
kanera standalone create "Reading list" --templateId simple-todo
kanera doctor # diagnose credentials and connectivityHow it is built
The CLI does not re-implement the public API. It opens an MCP session against the same tool layer
@kanera/mcp serves over HTTP and stdio, then exposes those tools as commands. With an API key the
session is in-process: nothing crosses a socket, InMemoryTransport links the two ends
directly. With an OAuth sign-in it connects to the remote MCP endpoint, because OAuth tokens
are issued for that endpoint and are never accepted by /api/v1.
That choice is the point: card-reference resolution (MKT-42), cursor encoding, response size
caps, and every tool description already live in that layer, so the CLI's command surface cannot
drift from what agents see over MCP, and a newly added tool is callable from the shell the day it
ships.
src/aliases.tsgives the high-traffic tools ergonomic names (kanera card done MKT-42). It is a convenience layer, not the surface; a test asserts every alias targets a real tool and only maps arguments that tool accepts.kanera call <tool>reaches anything the alias table does not cover.kanera commands --jsonis the machine-readable catalog agents use to discover the rest.
Credentials
Resolution order: --api-key, then KANERA_API_KEY, then a stored profile (OAuth sign-in or API
key). An explicit key always wins, so CI never runs through a developer's personal sign-in.
Profiles live in ~/.config/kanera/config.json (mode 600). Concurrent kanera processes take a
lock before refreshing an OAuth sign-in: Kanera rotates refresh tokens and revokes a sign-in whose
spent refresh token is presented twice, so parallel agent commands must not race. Named profiles let one machine hold
several identities:
kanera auth login --profile agent --api-key kanera_u_…
kanera --profile agent work --jsonThe non-secret, committable per-repo profile selection goes in .kanera/config.json:
{ "profile": "agent" }API origins are security-sensitive because they receive the bearer credential, so repository
configuration cannot set one. Use --url, KANERA_PUBLIC_API_URL, or the origin saved with a
profile during auth login. Non-loopback origins must use HTTPS.
Updates
At most once a day the CLI checks npm for a newer release. If it finds one, it asks
Update now? [y/N] after your command finishes, and y runs npm install --global @kanera/cli@<version>.
It only asks when a person is at an interactive terminal. It never checks or asks in --json or
--quiet mode, when stdin or stdout is not a TTY (which covers agents, scripts and pipes), under
CI, or when the CLI was launched through npx. Set KANERA_NO_UPDATE_CHECK=1 to turn the check off.
Output
| Flag | Output |
| ---- | ------ |
| (none) | Human-readable tables and summaries |
| --json | { ok, tool, data } envelope |
| --quiet | The bare result, for jq |
Failures always go to stderr, so redirecting stdout to a file never mixes an error envelope into what the caller believes is result data.
Rate-limit and transient API failures include retryable and, when supplied by the server,
retryAfter fields in structured output.
Exit codes
| Code | Meaning | | ---- | ------- | | 0 | success | | 1 | the request failed | | 2 | bad usage | | 3 | no valid credential | | 4 | forbidden — often a read-only credential | | 5 | not found | | 6 | rate limited |
4 is deliberately distinct from 1: an agent holding a read-scoped key needs to tell "I may not
do this" apart from "this did not work", and stop rather than retry.
Arguments
Flags map onto tool arguments and are coerced using the tool's own JSON Schema, never by how the value looks — a card key can look numeric and an id can look boolean.
Unknown flags, missing required arguments, malformed --json-args, and surplus positionals are
usage errors. The CLI never silently discards an operand.
kanera card update MKT-42 --changes.title "Revised" # dots nest
kanera work --scope.boardIds[] abc --scope.boardIds[] def # repeat or [] for arrays
kanera call cards.update --json-args '{"cardId":"MKT-42","changes":{"title":"Revised"}}'An array-typed argument also takes one JSON array, which is the simplest way to pass a list of objects, such as a whole checklist plan:
kanera call checklists.create --cardId MKT-42 --title Launch \
--items '[{"text":"Prepare release","subChecklists":[{"title":"Verification","items":[{"text":"Run smoke tests"}]}]},{"text":"Announce launch"}]'Agent setup
kanera setup claude # writes .claude/skills/kanera/SKILL.md
kanera setup codex # appends Kanera instructions to AGENTS.md
kanera skill # print the portable Agent Skill document for another harness
kanera mcp # serve the same tools over stdio MCP, using the stored credentialBoth setup targets teach the complete card workflow: start a run before substantive work, keep progress visible, post an outcome comment with verification and links, and move to the board's appropriate list before the final reply. Review is the default when acceptance remains; completion follows the user's instructions or established workflow. Read-only and exploratory requests cause no tracking writes, and explicit user restrictions take precedence.
After upgrading, replace an existing Claude skill with kanera setup claude --force. Existing
AGENTS.md sections are preserved; refresh yours from kanera skill if it lacks the work loop.
kanera mcp means a user who has already run kanera auth login does not configure a second
credential in a second place to use Kanera from an MCP client.
When connected Kanera MCP tools are already available, prefer them over the CLI. The CLI is the fallback for shell-only agents; both transports should be used instead of browser automation for supported card and project operations.
