@atollhq/cli
v0.5.10
Published
Atoll CLI — project management from the terminal
Maintainers
Readme
@atollhq/cli
Atoll CLI — project management from the terminal.
Install
npm install -g @atollhq/cli
# or run without installing
npx @atollhq/cli --helpAuthenticate
atoll auth login --key sk_atoll_...
atoll auth setup
atoll auth manage
atoll auth statusAgent API keys are created in the Atoll web app under Agents. Integration keys are still managed from Settings > Members.
Multiple auth profiles
Use profiles when you have multiple agent keys with different org or project access:
atoll auth login --profile agent-a --key sk_atoll_... --org-id org-uuid
atoll auth login --profile agent-b --key sk_atoll_... --org-id org-uuid --project project-uuid --team team-uuid
atoll auth login --profile local --key sk_atoll_... --org-id org-uuid --base-url http://localhost:3000
atoll auth setup
atoll auth manage
atoll auth profiles
atoll auth use agent-a
atoll auth delete-profile agent-b --forceRun a single command with a specific profile:
atoll --profile agent-b issue list
atoll --profile agent-a --org-id org-uuid issue create --title "Fix login bug"Each profile can store its own API key, default org ID, default team, default project, and base URL. --org-id, --team, and command-specific --project flags still override the selected profile for a single command.
For named profiles, always persist --org-id or pass --org-id per command. Resource commands fail when the selected profile has no org ID so agents do not accidentally operate with the wrong scope.
When a default team is configured, atoll issue list filters by that team and atoll issue create assigns new issues to that team. Team defaults can be a team ID or slug.
Use atoll auth profiles for a quick read-only list, atoll auth manage for an interactive profile menu, and atoll auth delete-profile <name> --force for scripted cleanup.
Profiles created by older CLI versions may contain a legacy orgSlug instead of orgId. atoll auth profiles and atoll config show label that state as a legacy slug. The next API command that fetches your accessible org list migrates it automatically when the slug matches exactly one org; if it cannot be matched safely, run atoll config set-org <org-id> once.
Usage
atoll issue list
atoll issue list --project <project-id>
atoll issue list --scope blocked --initiative initiative-uuid --order-by due_date --order-dir asc
atoll heartbeat
atoll issue create --title "Fix login bug" --priority 1
atoll issue create --title "Plan rollout" --project project-slug --description-file ./plan.md --milestone "Launch"
atoll issue create --title "Weekly status review" --due-date 2026-07-06 --recurrence weekly
atoll issue bulk-create --file ./issues.json --continue-on-error
atoll issue upsert --match-title --project project-uuid --title "Plan rollout" --status todo
atoll issue view ATOLL-42
atoll issue update ATOLL-42 --due-date 2026-05-15 --assignees member-1,member-2
atoll issue update ATOLL-42 --status in_progress --comment-body "Starting this because the activation KPI is off pace."
atoll issue bulk-update --file ./updates.json --dry-run
atoll label list
atoll label add ATOLL-42 bug
atoll notification list --json
atoll notification ack notification-uuid
atoll subtask create ATOLL-42 --title "Verify recurrence"
atoll activity issue ATOLL-42
atoll api get /api/orgs/$ATOLL_ORG_ID/labels --json
atoll plan validate --file ./plan.json
atoll plan apply --file ./plan.json --dry-run
atoll project list
atoll project delete <project-id> --confirm DELETE
atoll milestone list --project <id>
atoll milestone upsert --project <id> --name "v1.0" --date 2026-06-01
atoll goal create --title "Reach 100 paying customers by Q2" --target-date 2026-06-30
atoll kpi create --name paying_customers --goal "Reach 100 paying customers by Q2" --unit count --target 100
atoll kpi snapshot add paying_customers --value 34 --note "Checked Stripe dashboard"
atoll initiative create --title "Launch onboarding" --status active
atoll initiative kpi link "Launch onboarding" paying_customers --impact "+30 customers/mo"
atoll kpi snapshot add paying_customers --value 42 --initiative "Launch onboarding" --issue ATOLL-42 --note "Experiment shipped"
atoll kpi snapshot list paying_customers --include-attribution --json
atoll heartbeat --explain-kpi paying_customers --json
atoll initiative issue link "Launch onboarding" ATOLL-42
atoll dependency list ATOLL-42
atoll dependency bulk-add --file ./dependencies.json --continue-on-error
atoll config showRun atoll --help or atoll <command> --help for the full reference.
Configuration
The CLI stores state in ~/.atoll/config.json. You can override the profile, org, or team per-command:
atoll --profile agent-a issue list
atoll --org-id org-uuid issue list
atoll --team eng issue create --title "..."
atoll issue create --project project-slug --title "..."
atoll --env-mode issue listProfiles are the recommended persistent configuration for developer and agent machines. Env vars remain supported for CI, containers, and one-off commands: ATOLL_PROFILE, ATOLL_API_KEY, ATOLL_ORG_ID, ATOLL_TEAM, ATOLL_PROJECT, ATOLL_BASE_URL, and ATOLL_ENV_MODE.
When a profile is selected, ambient ATOLL_* env vars do not silently override profile context. Conflicting env values fail before network calls. Pass --profile, add repo-local .atoll/context.json, or use --env-mode / ATOLL_ENV_MODE=1 for CI-style env usage.
For OpenClaw / ClawHub skill usage, prefer configuring the atoll skill under skills.entries.atoll in ~/.openclaw/openclaw.json instead of relying on global shell exports. Keep the CLI profile for direct atoll ... commands; the OpenClaw skill config provides the env expected by the ClawHub skill.
atoll config show prints where each resolved value came from, such as $ATOLL_API_KEY,
~/.atoll/config.json, or a named profile in that config file. This helps distinguish
fresh installs from previously saved local configuration.
Set default project, team, or base URL values for the selected profile:
atoll config set-project project-uuid
atoll config set-team team-slug
atoll config set-base-url https://atollhq.com
atoll config clear-projectWhen a default project is configured, atoll issue list, atoll issue create,
atoll issue upsert --match-title, atoll milestone list, atoll milestone create,
and atoll milestone upsert use it unless --project is passed.
When a default team is configured, atoll issue list, atoll issue create, and new issue upsert creates use it unless --team is passed.
Long text and issue fields
Use file flags for Markdown-heavy descriptions and comments:
atoll issue create --title "Add dependency commands" --description-file ./issue.md
atoll issue update ATOLL-42 --description-file -
atoll issue update ATOLL-42 --status in_progress --comment-body-file ./strategy-progress.md
atoll milestone create --name "CLI safety" --description-file ./milestone.md
atoll comment add ATOLL-42 --body-file ./progress.md
atoll comment add ATOLL-42 --body "Tagging by ID" --mention-member member-uuid
atoll comment add ATOLL-42 --body "Tagging by exact display name" --mention "Raphael Ubales"
atoll comment update <comment-id> --issue ATOLL-42 --body-file ---description-file -, --comment-body-file -, and --body-file - read stdin. File flags are mutually exclusive with their inline equivalents. Use --comment-body with status updates when you need the progress note to be created durably in the same issue update.
Use --mention-member <member-id> for reliable structured comment mentions; repeat it to mention multiple members. --mention "<display-name>" performs a case-insensitive exact display-name lookup and exits with candidate member IDs if the name is ambiguous. It does not do fuzzy matching.
Issue create/update can set common planning fields:
atoll issue create \
--title "Implement richer mutation flags" \
--project project-slug \
--milestone "Launch" \
--start-date 2026-05-13 \
--due-date 2026-05-15 \
--recurrence weekly \
--labels bug,launch \
--assignees member-1,member-2
atoll issue update ATOLL-42 --clear-milestone --clear-due-date --clear-recurrence --clear-assignees
atoll issue update ATOLL-42 --clear-descriptionUse atoll label add ATOLL-42 bug and atoll label remove ATOLL-42 bug for existing tasks. --labels is accepted on issue create, not issue update.
On issue create, --project accepts a project ID, slug, or exact name. --milestone accepts a milestone ID, or an exact milestone name when a project is selected with --project or the active profile's default project.
When moving an issue to another project with --project, the CLI clears the existing milestone unless --milestone is also provided.
Bulk issue operations
Use file-based bulk commands when syncing batches from a plan or generated task list:
atoll issue bulk-create --file ./issues.json --continue-on-error --max-concurrency 4
atoll issue bulk-update --file ./updates.json --dry-runFiles can be a JSON array or an object with an issues array. bulk-create items use the same field names as issue create (title, description, status, priority, projectId, teamId, milestoneId, startDate, dueDate, recurrenceType, recurrenceInterval, labelIds, assigneeId, assigneeIds). bulk-update items require identifier (or issue/id/key) plus one or more mutable fields, including recurrenceType, recurrenceInterval, or clearRecurrence. Both commands report { requested, succeeded, alreadyExisted, failed, results }; use --continue-on-error to process the whole file after failures. Exit code is non-zero only when at least one item fails.
Labels, notifications, subtasks, activity, and API fallback
atoll label list
atoll label create --name bug --color "#dc2626"
atoll label add ATOLL-42 bug
atoll label remove ATOLL-42 bug
atoll notification list --json
atoll notification ack notification-uuid
atoll subtask list ATOLL-42
atoll subtask create ATOLL-42 --title "Verify recurrence"
atoll subtask update ATOLL-42 subtask-uuid --completed
atoll activity list --filter by_me --json
atoll activity issue ATOLL-42
atoll api get /api/orgs/$ATOLL_ORG_ID/labels --jsonatoll api get is GET-only and only accepts Atoll paths under /api/, but GET is not a promise that the server does no work. The CLI blocks /api/internal/*, billing, and KPI sync admin routes because those workflows can run jobs, synchronize external state, or require human-admin review. Use it for uncommon inspection gaps, not for internal jobs, billing, KPI sync lifecycle, or other human-admin-gated workflows unless a typed command explicitly supports the action.
Idempotent upserts
Use upsert commands for retry-safe planning sync:
atoll milestone upsert --project project-uuid --name "CLI safety" --date 2026-06-01
atoll issue upsert ATOLL-42 --status in_progress
atoll issue upsert --match-title --project project-uuid --title "Implement CLI safety" --priority 1milestone upsert matches exact milestone names within the selected project. issue upsert --match-title matches exact issue titles within the selected project. Ambiguous matches fail before mutation. Add --dry-run to return the intended created, updated, or unchanged action without changing Atoll.
Dependencies
Issue dependencies can be managed by issue key or UUID:
atoll dependency list ATOLL-42
atoll dependency add ATOLL-42 --blocked-by ATOLL-41
atoll dependency add ATOLL-42 --blocks ATOLL-43
atoll dependency bulk-add --file ./dependencies.json --continue-on-error
atoll dependency remove ATOLL-42 <dependency-id>Direction is relative to the issue argument. --blocked-by ATOLL-41 means ATOLL-42 waits on ATOLL-41. --blocks ATOLL-43 means ATOLL-42 blocks ATOLL-43.
Adding an existing dependency succeeds by default so retries are safe. Pass --strict to treat duplicates as errors.
For bulk-add, files can be a JSON array or an object with a dependencies array. Each item requires identifier (or issue/id) and exactly one of blockedBy/blocked_by or blocks/blocking; duplicate edges are reported as already_satisfied.
Plan files
Use plan validate and plan apply when syncing a graph of milestones, issues, dependencies, and initiative links from one file:
atoll plan validate --file ./plan.json
atoll plan apply --file ./plan.json --dry-run
atoll plan apply --file ./plan.jsonPlan files use schemaVersion: "atoll.plan.v1" and local key values for cross-resource references:
{
"schemaVersion": "atoll.plan.v1",
"project": "app",
"milestones": [
{ "key": "mvp", "name": "MVP", "date": "2026-06-01" }
],
"issues": [
{ "key": "api", "title": "Build API", "status": "todo", "priority": 1, "milestoneKey": "mvp" },
{ "key": "docs", "title": "Write docs", "dependsOn": ["api"], "initiative": "Launch" }
],
"dependencies": [
{ "issue": "docs", "blockedBy": "api" }
],
"initiativeLinks": [
{ "initiative": "Launch", "issueKey": "api" }
],
"milestoneLinks": [
{ "initiative": "Launch", "milestoneKey": "mvp" }
]
}plan validate checks schema version, duplicate keys, missing local references, invalid priorities/statuses/dates, and dependency cycles without contacting the API. plan apply upserts milestones by exact name, upserts issues by identifier or exact title within the selected project, then applies dependencies and initiative links. Duplicate dependencies and links are reported as already_satisfied so retries are safe. JSON output reports { requested, changed, unchanged, alreadySatisfied, results }.
Initiatives
Initiatives can be managed by ID, exact title, or legacy name:
atoll initiative list --status active
atoll initiative create --title "Launch onboarding" --description-file ./initiative.md --target-date 2026-06-30
atoll initiative view "Launch onboarding"
atoll initiative update "Launch onboarding" --status completedUse nested link commands to connect initiatives to execution work:
atoll initiative issue link "Launch onboarding" ATOLL-42
atoll initiative issue unlink "Launch onboarding" ATOLL-42
atoll initiative milestone link "Launch onboarding" "v1.0" --project app
atoll initiative milestone unlink "Launch onboarding" "v1.0" --project appIssue links accept UUIDs, issue keys, or exact issue titles. Milestone names are resolved within --project or the configured default project; milestone UUIDs do not need a project.
Adding an existing initiative link succeeds by default so retries are safe. Pass --strict to treat duplicates as errors.
Agent-friendly output
Use --json on any command to emit machine-readable output:
atoll --json issue list
atoll heartbeat --json
atoll agent-contextList commands return a bounded object:
{
"resource": "issues",
"items": [],
"total": 0,
"limit": 25,
"offset": 0,
"nextOffset": null,
"truncated": false,
"hint": null
}Project-scoped atoll issue list --json also includes one top-level project_context object with board column metadata and optional stage guidance. atoll issue get --json and atoll issue view --json include the issue's current status_column plus project_context when the issue belongs to a project.
Diagnostics and errors are written to stderr. API failures preserve the upstream status/code/details in JSON mode and add safe command context plus remediation guidance, without printing API keys or secrets:
{
"error": "Forbidden",
"status": 403,
"code": "permission_denied",
"details": { "resource": "issues" },
"operation": "issue.list",
"request": { "method": "GET", "path": "/api/orgs/org-id/issues?limit=25" },
"context": { "profile": "agent-a", "orgId": "org-id", "defaultProject": "project-id" },
"guidance": "Check that the selected profile has access to the org/project for issue.list. Use --profile/--org-id if needed."
}Interactive update notices are also written to stderr and are suppressed for --json, non-TTY output, CI, and shell completions. Agents should read structured update state from the cli object instead of parsing human notices.
Heartbeat
Heartbeat is the primary agent orientation command:
atoll heartbeat
atoll heartbeat --signals-only
atoll heartbeat --severity critical
atoll heartbeat --jsonIt wraps GET /api/orgs/{orgId}/heartbeat and returns active goals, KPI pace, initiative health, assigned work, prioritized signals, and a deterministic recommended_action when Atoll can propose one concrete strategy-backed next action.
atoll heartbeat --signals-only prints only the current signals plus the recommended action. JSON heartbeat output includes project_context for relevant project boards, recommended_action, plus a cli object with the installed CLI version, latest known npm version when available, update_available, and update_command. atoll heartbeat --signals-only --json keeps recommended_action alongside the filtered signals.
For agents, recommended_action.usage_guidance explains how to apply the proposal: prefer suggested_write.operation when it still matches the board, preserve KPI/initiative/initiative-target/why-now/expected-impact/first-step/success-criteria evidence, and avoid copying deferred busywork into issue or comment payloads. If a start_work recommendation uses issue.update with a body, update the issue status and preserve that body as an issue comment; PATCH /issues/{issueId} accepts comment_body for this same-request progress note.
Strategy
Use the Strategy commands to create the same goal/KPI/initiative chain exposed in the web app:
atoll goal list
atoll goal create --title "Reach 100 paying customers by Q2" --target-date 2026-06-30
atoll kpi create --name paying_customers --goal "Reach 100 paying customers by Q2" --unit count --target 100 --current 34
atoll initiative create --title "Content pipeline" --goal "Reach 100 paying customers by Q2" --status active
atoll initiative kpi link "Content pipeline" paying_customers --impact "+30 customers/mo"
atoll kpi snapshot add paying_customers --value 42 --initiative "Content pipeline" --issue ATOLL-42 --note "End-of-week Stripe check"
atoll kpi snapshot list paying_customers --include-attribution --jsonThe web UI has a setup wizard for first-time users. The CLI mirrors the same primitives for agents, scripts, imports, and local automation: create a goal, attach KPIs, record snapshots, create initiatives, and declare expected KPI impacts.
KPI HTTP sync drafts
Agents can help configure third-party KPI polling, but the CLI only supports draft creation and config validation without third-party network execution. A human admin must allowlist the exact destination host in Atoll before these commands can succeed. Human admins also use Atoll to enter secrets, dry-run, publish, disable, or write snapshots.
atoll kpi sync validate <kpi-id> \
--name "PostHog visitors" \
--schedule daily \
--url https://us.posthog.com/api/projects/123/query/ \
--pointer /results/0/value \
--auth-secret-ref posthog_api_key
atoll kpi sync draft <kpi-id> --file sync-draft.jsonDraft files must not include secret values or query strings:
{
"name": "PostHog visitors",
"schedule": "daily",
"request_config": {
"method": "GET",
"url": "https://us.posthog.com/api/projects/123/query/",
"headers": {
"Authorization": {
"secretRef": "posthog_api_key",
"format": "Bearer {value}"
}
}
},
"extraction_config": {
"contentType": "json",
"pointer": "/results/0/value",
"numeric": {
"mode": "number",
"percentageScale": null
}
},
"freshness_config": {}
}V1 syncs are GET-only, https-only, JSON-only, exact-host allowlisted, no redirects, no bodies, and no inline query strings. Credential placeholders are limited to Authorization: Bearer <secretRef> and X-API-Key: <secretRef>.
Agent context
atoll agent-context emits a versioned JSON description of the CLI surface, selected profile/org context, known command flags, enum values, and available Atoll skill manifests.
It also includes the same structured cli update metadata as heartbeat JSON.
atoll agent-context | jq '.schema_version, .commands.heartbeat'Skill update prompt
When @atollhq/cli is installed or updated in an interactive terminal, its postinstall hook checks whether the local Codex Atoll skill at ~/.codex/skills/atoll/ is behind @atollhq/skill-codex@latest. It also detects the legacy ~/.codex/skills/atoll-api/ path and offers to install the renamed atoll skill.
If an update is available, it asks before making changes:
Update the Atoll Codex skill now? [y/N]Non-interactive installs, CI, and installs with --ignore-scripts skip this check.
Safer deletion
Permanent delete commands require --force and support --dry-run:
atoll issue delete ATOLL-42 --dry-run
atoll issue delete ATOLL-42 --force
atoll comment delete <comment-id> --issue ATOLL-42 --force
atoll webhook delete <id> --forceFor issues, prefer reversible archive:
atoll issue archive ATOLL-42
atoll issue unarchive ATOLL-42Feedback
Send CLI or platform friction upstream:
atoll feedback "the --status error should list custom board statuses"Save an explicit local draft or retry a failed send:
atoll feedback draft "heartbeat should include issue_blocked signals"
atoll feedback drafts
atoll feedback view fb_123
atoll feedback resend fb_123Use --file <path> or --file - for multiline reports. Set ATOLL_FEEDBACK_ENDPOINT to override the destination.
Output URLs
Issue and project JSON output includes a canonical url field pointing at the Atoll web app (honoring ATOLL_BASE_URL for self-hosted / local dev), suitable for pasting into standups, notifications, and follow-ups:
atoll issue view ATOLL-42 | jq -r .url
# https://atollhq.com/acme/projects/atoll/issues/42url is null for orphan issues (no project) or missing identifiers, so consumers should handle that case.
License
MIT
