@customerio/cli

中文文档
0.0.37发布于 2026/11/03SEE LICENSE IN LICENSE零依赖构建来源已验证近 30 天下载 1.1万

Agent-first CLI for Customer.io APIs

原始使用文档
文档目录21 节
  1. Install
  2. Uninstall
  3. Install the agent skill
  4. Authentication
  5. New to Customer.io?
  6. Login
  7. Token Resolution Order
  8. Profiles
  9. How It Works
  10. Override per-command
  11. Usage
  12. Account ID fallback
  13. Filtering with jq
  14. Write operations
  15. Pagination
  16. Global Flags
  17. Exit Codes
  18. Error Format
  19. Architecture
  20. Development
  21. License

Customer.io CLI (cio)

An agent-first CLI for Customer.io APIs.

800+ Journeys routes + 100+ CDP Pipelines routes, zero per-endpoint code. A single cio api <path> command covers every endpoint. Every command returns structured JSON to stdout. Every error returns structured JSON to stderr.

AI agents are the primary consumer. Use cio schema to introspect endpoints before calling them.

Install

npm i -g @customerio/cli
cio --help

To build from source instead:

go install github.com/customerio/cli@latest

Uninstall

# If installed via npm
npm uninstall -g @customerio/cli

# If installed via go install
rm -f "$(go env GOPATH)/bin/cio"

To remove stored credentials and cached data:

rm -rf ~/.cio

Install the agent skill

This repo ships a SKILL.md so Claude Code, Cursor, Codex, Windsurf, and other agents that support open agent skills know how to drive the CLI.

The CLI can install the current skills directly:

# Installs the bootstrap skill; prompts for global (~/.claude, ~/.agents)
# vs. project (./.claude, ./.agents)
cio skills install

cio skills install --global          # install for every project
cio skills install --project         # install into the current directory
cio skills install --target claude   # Claude Code only (use --target codex for Codex)
cio skills install --dry-run         # show what would be written
cio skills install --force           # overwrite an existing SKILL.md

This installs only the Customer.io bootstrap skill — its SKILL.md routing index is written to <target>/skills/<name>/ for Claude Code (.claude) and the open agent skills convention (.agents) Codex, Cursor, and Windsurf read. Every other reference (Journeys, CDP, Design Studio, recipes) is served by the backend and pulled on demand via cio skills read <skill>, so nothing else is copied locally and the content stays current.

Or install via the open agent skills tooling:

npx skills add customerio/cli

Authentication

The CLI uses service account tokens (sa_live_...) for authentication. These are exchanged for short-lived JWTs via OAuth 2.0 client credentials, just like gh auth.

New to Customer.io?

Create an account from the CLI. start emails you a 6-digit code, and verify checks it, creates the account and saves its credentials, so you don't need to log in afterward.

cio auth signup start --json '{"email":"[email protected]"}'

cio auth signup verify --json '{
  "email": "[email protected]",
  "code": "123456",
  "company_name": "Acme",
  "first_name": "Ada",
  "last_name": "Lovelace",
  "data_center": "us"
}'

data_center is us or eu. AI agents can run this for the user; the full flow is in cio skills read cio/auth.md.

Login

# Interactive — prints the browser login URL, then prompts for the minted token
cio auth login

# Read from stdin (for CI/automation; login still auto-discovers region)
echo "$SA_TOKEN" | cio auth login --with-token

# Verify auth works
cio auth status

# Print raw token
cio auth token

# Logout
cio auth logout

Token Resolution Order

  1. --token flag (highest priority)
  2. CIO_TOKEN environment variable
  3. ~/.cio/config.json file (lowest priority)

When you use CIO_TOKEN or --token directly on normal commands, you may also need CIO_REGION=us|eu or --api-url.

Profiles

Keep multiple credential sets — production, staging, several client accounts — in one config file and switch between them. Each profile has its own token, region, and optional custom base URL.

# Log into a named profile (custom --api-url is remembered; switches to it)
echo "$STAGING_TOKEN" | cio auth login --profile staging --with-token --api-url https://<staging-host>

# List profiles (the saved default is marked current)
cio profile list

# Use a profile for one command…
cio --profile staging api /v1/campaigns
# …or a whole session
export CIO_PROFILE=staging

# Change the default, or remove a profile
cio profile use default
cio profile remove staging

Profile resolution: --profile flag → CIO_PROFILE → stored current_profile → default. An existing single-credential config is migrated to a default profile automatically. Profile names may contain letters, digits, ., -, and _.

cio auth login without --profile re-authenticates whichever profile is currently selected, not always default — pass --profile <name> to target a specific one. cio profile list marks the saved default (current_profile), which a per-command --profile / CIO_PROFILE override does not change.

How It Works

  1. You provide a service account token (sa_live_... from Customer.io UI → Account Settings → Manage API Credentials → Service Accounts), or cio auth signup verify saves one for a new account
  2. The CLI exchanges it for a JWT via POST /v1/service_accounts/oauth/token
  3. The JWT is cached locally and refreshed automatically when it expires
  4. All API calls use Authorization: Bearer <jwt>

Override per-command

cio --token sa_live_xxx api /v1/environments/{environment_id}/campaigns --params '{"environment_id": "123"}'
CIO_TOKEN=sa_live_xxx cio api /v1/environments/{environment_id}/campaigns --params '{"environment_id": "123"}'

Usage

Use cio api <path> for any API endpoint. Path placeholders are resolved from --params. The HTTP method defaults to GET (or POST if --json is provided); override with -X:

--params takes a JSON object; URL-query syntax (--params 'type=event&size=200') is also accepted. Repeat --params to split values across flags (--params type=event --params size=200); a key given more than once is an error. In the query form a bare + is rejected as ambiguous — write %20 for a space and %2B for a plus (email=a%[email protected]), or use the JSON form, where both are literal.

# List campaigns in workspace 123
cio api /v1/environments/{environment_id}/campaigns --params '{"environment_id": "123"}'

# Get a specific campaign
cio api /v1/environments/{environment_id}/campaigns/{campaign_id} \
  --params '{"environment_id": "123", "campaign_id": "456"}'

# Create a campaign
cio api /v1/environments/{environment_id}/campaigns \
  --params '{"environment_id": "123"}' \
  --json '{"campaign": {"name": "Welcome Flow", "type": "none"}}'

# Explicit method override
cio api /v1/environments/{environment_id}/campaigns/{campaign_id} -X DELETE \
  --params '{"environment_id": "123", "campaign_id": "456"}'

# Introspect endpoints
cio schema                          # list all resources
cio schema campaigns                # list endpoints for a resource
cio schema campaigns.list           # full schema for a method
cio schema GET /v1/environments/{environment_id}/campaigns  # by HTTP method + path
cio schema campaigns.list --compact # flattened one line per field instead of JSON Schema

Account ID fallback

Paths that include {account_id} auto-fill from the account ID stored during cio auth login, so you don't need to pass it on every call:

cio api /v1/accounts/{account_id}/environments

Pass --params '{"account_id": "..."}' to override, or set CIO_ACCESS_TOKEN to disable the fallback (the pre-exchanged JWT may belong to a different account).

Filtering with jq

# Filter with --jq to save context window
cio api /v1/environments/{environment_id}/campaigns \
  --params '{"environment_id": "123"}' \
  --jq '.campaigns[] | {id, name, state}'

# Complex filtering
cio api /v1/environments/{environment_id}/campaigns \
  --params '{"environment_id": "123"}' \
  --jq '.campaigns[] | select(.state == "active") | {id, name}'

Write operations

# Always dry-run first
cio api /v1/environments/{environment_id}/campaigns \
  --params '{"environment_id": "123"}' \
  --json '{"campaign": {"name": "Welcome Flow", "type": "none"}}' --dry-run

# Then execute (removes --dry-run)
cio api /v1/environments/{environment_id}/campaigns \
  --params '{"environment_id": "123"}' \
  --json '{"campaign": {"name": "Welcome Flow", "type": "none"}}'

Pagination

cio api /v1/environments/{environment_id}/campaigns \
  --params '{"environment_id": "123"}' --page 2 --limit 50

# Auto-paginate (emits NDJSON — one JSON object per line)
cio api /v1/environments/{environment_id}/campaigns \
  --params '{"environment_id": "123"}' --page-all

Global Flags

FlagEnv VarDescription
--token <value>CIO_TOKENService account token override
--profile <name>CIO_PROFILEConfiguration profile to use
-X, --methodHTTP method override (default: GET, or POST if --json)
--json <payload>Raw JSON request body or @filename to read from file
--params <json>Query parameters as JSON → query string
--jq <expr>jq expression filter (via gojq)
--dry-runValidate + print request, skip execution
--api-url <url>API base URL override
--timeout <duration>CIO_TIMEOUTHTTP request timeout (default: 30s)
--page <n>Page number
--limit <n>Page size
--page-allAuto-paginate, emit NDJSON

cio api retries timeouts for GET and HEAD, and for writes only when the request was not sent. Writes whose response times out after sending are not retried because they may already have applied. --timeout still bounds each HTTP attempt and defaults to 30s.

Timeouts share the existing retry limit and exponential backoff with HTTP 429 and retryable 5xx responses. CIO_MAX_RETRIES defaults to 3 retries, or 4 total attempts; set it to 0 to disable these retries. Caller cancellation or an expired caller deadline stops retries. Repeated timeouts can therefore take longer than --timeout overall. If --page-all exhausts its retries, it exits with an error and leaves any earlier pages in stdout; callers must check its exit status before using the output as a complete result.

Exit Codes

CodeMeaning
0Success
1General error
2Validation / input error
3Authentication error
4Authorization error
5API error (4xx/5xx)

Error Format

{"error":true,"code":"AUTH_ERROR","message":"Not authenticated.","details":{"status_code":401}}

Architecture

The CLI uses a generic api command + route registry architecture:

  1. cio api <path> — a single command that takes any API path with {placeholder} params
  2. OpenAPI specs are downloaded from the live API on first use and cached locally under ~/.cio/cache/specs/ (24h TTL, ETag-based conditional refresh). Use cio schema --refresh to force re-download.
  3. internal/routes/enrichment.json — summaries, param descriptions, query params for routes not yet annotated in the OpenAPI spec
# Discover resources
cio schema

# List endpoints for a resource
cio schema campaigns

# Inspect a method's parameters
cio schema campaigns.list

# Make an API call
cio api /v1/environments/{environment_id}/campaigns --params '{"environment_id": "123"}'

# CDP Pipelines (workspace_id = environment_id)
cio api /cdp/api/workspaces/{workspace_id}/sources --params '{"workspace_id": "123"}'
cio schema sources

Development

go build -o cio .
go test ./...
go test ./... -v -run TestAuthLogin

License

Licensed under Apache License 2.0 with the Commons Clause Restriction. See LICENSE.

版本与发布记录

@customerio/cli 共发布 42 个版本,首次发布于 2026/04/29;过去 12 个月发布了 42 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.0.37latest2026/11/038 天前
0.0.362026/10/2715 天前
0.0.352026/10/2615 天前
0.0.342026/10/2418 天前
0.0.332026/10/2418 天前
0.0.322026/10/2121 天前

其他发布通道:bootstrap → 0.0.0-bootstrap,alpha → 0.0.18-alpha.1。

关于 @customerio/cli 的常见问题

@customerio/cli 是什么?

Agent-first CLI for Customer.io APIs

如何安装 @customerio/cli?

在项目目录运行 npm install @customerio/cli,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 cio,可以用 npx cio 直接运行。

@customerio/cli 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/customerio__cli 是否存在。

@customerio/cli 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=16。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@customerio/cli 可以商用吗?

@customerio/cli 使用 SEE LICENSE IN LICENSE 许可。许可条款写在包内的独立文件中,请阅读该文件确认可否商用。以上为概括,不构成法律意见,请以许可原文为准。

@customerio/cli 的下载量有多少?

根据 npm 官方下载统计,@customerio/cli 在 2026/10/11 – 2026/11/09 这 30 天内被下载 11,311 次,日均约 377 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@customerio/cli 还在维护吗?

最新版本 0.0.37 发布于 2026/11/03(8 天前);至今共发布 42 个版本,其中过去 12 个月发布了 42 个;首次发布于 2026/04/29。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。