Command-line interface for Otper — manage boards, lists, cards, labels, and comments from your terminal. Talks directly to the Otper GraphQL API and is also embeddable as a Node library.
npm install -g @ssntpl/otper-cli
otper auth:login
otper board:search "engineering"
otper card:list --list 42- Install
- Authentication
- Configuration
- Command reference
- Output formats
- Library usage
- Examples
- Contributing
- License
Requires Node.js 18+.
npm install -g @ssntpl/otper-cliTo use it programmatically in another Node project (no global install needed):
npm install @ssntpl/otper-cliOtper uses Bearer tokens. Generate a personal access token at https://otper.com/settings/tokens, then:
otper auth:login
# Otper API token: ********************
# ✓ Authenticated as Sambhav Aggarwal (@sam)
# saved to /Users/you/.otper-cli/default/config.jsonYou can also pass the token directly:
otper auth:login --token "238|abc..." --base-url https://otper.com --team ssntplOr skip the saved config and use environment variables (handy for CI):
export OTPER_TOKEN="238|abc..."
export OTPER_BASE_URL="https://otper.com"
otper board:search engineeringTo sign out:
otper auth:logoutSet OTPER_PROFILE to maintain isolated config files per environment:
OTPER_PROFILE=staging otper auth:login --base-url https://staging.otper.com
OTPER_PROFILE=staging otper board:listCredentials are stored at ~/.otper-cli/<profile>/config.json with mode 0600. The file looks like:
{
"baseUrl": "https://otper.com",
"token": "238|...",
"team": "ssntpl"
}Resolution order (highest priority first):
- Command-line flags:
--token,--base-url - Environment variables:
OTPER_TOKEN,OTPER_BASE_URL,OTPER_TEAM - Saved config file
Run otper <topic> --help to see commands within a topic, and otper <topic>:<command> --help for full flag documentation.
| Command | Description |
|---|---|
otper auth:login [token] |
Save credentials to the active profile. |
otper auth:logout |
Remove the saved credentials. |
otper auth:whoami |
Show the user the token authenticates as. |
| Command | Description |
|---|---|
otper board:list [-q query] |
List boards (alias for search). |
otper board:search <query> |
Search boards by name. |
otper board:show <id> |
Show a board by ID. Use --team --slug to look up by slug. |
otper board:create --team-id --name --key --slug |
Create a new board. |
| Command | Description |
|---|---|
otper list:list --board <id> |
List all lists on a board. |
otper list:show <id> [--page --search] |
Show a list with its cards. |
otper list:create --board --name |
Create a list. |
otper list:rename <id> [--name --description --color] |
Update a list. |
otper list:reorder <id> <to-id> |
Reorder a list relative to another. |
| Command | Description |
|---|---|
otper card:list --list <id> |
List cards in a list (paginated, 25/page). |
otper card:show <id> |
Show a card by ID. Use --slug to look up by slug. |
otper card:create --list --title |
Create a card. |
otper card:update <id> [--title --description --due-date ...] |
Update a card. |
otper card:move <id> --to-list <listId> [--over <cardId>] |
Move a card. |
otper card:assign <id> --user <userId> |
Assign a user (repeat --user for many). |
otper card:unassign <id> --user <userId> |
Unassign users. |
otper card:label <id> --label <labelId> |
Attach labels. |
otper card:unlabel <id> --label <labelId> |
Detach labels. |
otper card:comment <id> --text "..." |
Add a comment to a card. |
otper card:comments <id> |
List comments on a card (newest first). |
otper card:delete <id> [-y] |
Permanently delete a card. |
The --search flag on card:list and list:show accepts the same syntax as the Otper UI:
otper card:list --list 42 --search "labels:bug;assignee:alice;status:not completed"
otper card:list --list 42 --search "due date:overdue"
otper card:list --list 42 --search "#ENG123"| Command | Description |
|---|---|
otper label:list --board <id> |
List labels on a board. |
otper label:create --board --name [--color] |
Create a label. |
otper label:update <id> |
Update a label. |
otper label:delete <id> [-y] |
Delete a label. |
| Command | Description |
|---|---|
otper comment:update <id> --text "..." |
Edit a comment. |
otper comment:delete <id> [-y] |
Delete a comment. |
otper comment:react <id> --reaction like |
Toggle a reaction (like, love, laugh, wow, sad, angry). |
| Command | Description |
|---|---|
otper team:show <id> |
Show a team with members and boards. |
otper team:users <id> |
List members of a team. |
| Command | Description |
|---|---|
otper me |
Alias for auth:whoami. |
otper search <query> [--type boards|users] |
Search boards (default) or users. |
otper priorities [--user <id>] |
Today's priority cards for a user (defaults to you). |
Every command supports --format:
| Format | Description |
|---|---|
default |
Pretty table or vertical key/value (best for humans). |
json |
Pretty-printed JSON (best for piping into jq). |
csv |
RFC-4180 CSV (best for spreadsheets). |
silent |
No output, only an exit code (best for scripts). |
otper card:list --list 42 --format json | jq '.data[].title'
otper board:search team --format csv > boards.csv
otper card:move 1234 --to-list 50 --format silent && echo moved@ssntpl/otper-cli doubles as a typed library. Useful for openclaw plugins and other Node integrations:
import { OtperClient, boards, cards, lists } from '@ssntpl/otper-cli';
const client = new OtperClient({
baseUrl: 'https://otper.com',
token: process.env.OTPER_TOKEN!,
});
const board = await boards.getBoard(client, '7');
const inProgress = await lists.getListWithCards(client, '42', 1);
for (const card of inProgress!.cards.data) {
console.log(card.card_number, card.title);
}
await cards.moveCard(client, '1234', '50'); // → DoneYou can also load the user's saved config:
import { OtperClient, resolveConfig } from '@ssntpl/otper-cli';
const cfg = resolveConfig(); // throws if not authenticated
const client = OtperClient.fromConfig(cfg);For raw GraphQL escape-hatches:
const data = await client.gql<{ me: { id: string } }>(
`query { me { id name } }`,
);Daily standup digest — list everything in progress and pipe into a summary:
otper card:list --list 42 --format csv > inprogress.csvMove a card to Done in a script:
otper card:move "$CARD_ID" --to-list 120 --format silentReact to every unread comment (using jq):
otper card:comments "$CARD_ID" --format json \
| jq -r '.[] | select(.reactions == []) | .id' \
| xargs -I {} otper comment:react {} --reaction like --format silentUse a different token per command (no config required):
OTPER_TOKEN="$BOT_TOKEN" otper card:comment 1234 --text "Build queued"git clone git@github.com:ssntpl/otper-cli.git
cd otper-cli
npm install
npm run dev -- board:search hello # run from source via tsx
npm run build # compile to dist/
node bin/run.js --help # run the compiled CLIPRs welcome. Please:
- Add or update the README's command reference for any new commands.
- Keep GraphQL queries colocated in
src/api/<resource>.ts. - Mirror the existing
BaseCommand/Column/output()pattern when adding commands so--formatworks uniformly.
MIT © SSNTPL