| name | nca-cli-usage |
| description | How to drive the `nca` CLI (Netmind Cloud Agents) to inspect and configure a user's resources — login + scope grants, agents, agent-runtimes, channels (Telegram/Lark/Slack/Discord/Matrix), and the local daemon. Use this skill aggressively whenever the user mentions the `nca` command or any of its subcommands, asks to "create a channel", "wire up Telegram/Lark/Slack for my agent", "list my agents/runtimes", "register a daemon on my laptop", "log in to Cloud Agents from a sprite / headless / agent", "set up an agent runtime", "approve an OAuth scope grant", "configure my Cloud Agents account from the terminal", or shows a shell session with `NCA_AGENT_ID` / `NCA_API_URL` / `~/.config/nca/config.json`. Also trigger when the agent is running inside a hosted sprite and needs to act on the user's behalf via headless `nca login --poll`, when a 401 mentions "token missing scope", or when troubleshooting why an `nca` command says "agent id is required" / "not authenticated". Don't reach for raw `curl` against the Cloud Agents API before checking whether a CLI command already covers it. |
nca CLI usage
This skill teaches you how to use the nca CLI to read and configure a user's Cloud Agents resources. It works in two contexts:
- Hosted (inside a sprite/pod runtime). The agent has
NCA_API_URL and NCA_AGENT_ID already in its environment. There is no human at the terminal. To get an API token, the agent posts an OAuth consent URL to the user via chat and waits for approval.
- Local (on the user's laptop). The user runs
nca themselves, or asks Claude to draft commands for them. A browser is available, login goes through the normal flow.
The CLI's command tree is small but the auth model is the part that trips agents up. Read the Auth section before touching any other section.
Mental model
nca <global-flags> <command> [...]
# global flags (and matching env vars):
--api-url <url> NCA_API_URL e.g. https://nca-api.netmind.xyz/api
--token <token> NCA_TOKEN Clerk JWT or grant token (overrides ~/.config/nca/config.json)
--agent-id <id> NCA_AGENT_ID used by `login --for-agent` and `channels`
The config file ~/.config/nca/config.json (mode 0600) holds { apiUrl, token }. Every command except login and update reads it. Never print the file or echo $NCA_TOKEN — it is the user's grant token.
Auth — pick a mode
nca login has five modes. The flag combination picks the mode (see apps/cli/src/commands/login.ts:resolveLoginMode if you want the source of truth):
| Mode | When | Command |
|---|
browser | Local, has display | nca login |
headless | Local, no display | nca login --no-launch-browser (then paste auth code) |
auth-code | Already have a code from the web UI | nca login --auth-code <code> |
token | Already have a token | nca login --token <token> |
poll | Hosted agent acting for a user | nca login --poll --scopes <list> (uses $NCA_AGENT_ID) |
Hosted agent (poll mode) — the path you'll usually need
When a command fails because of missing scope, or you're starting fresh inside a sprite:
nca login --poll --scopes channels:read,channels:edit
The CLI prints a consent URL like https://agents.netmind.xyz/cli-login?request=…&code=…. Post that URL to the user in chat and ask them to approve. The CLI polls until they click approve, then writes the resulting grant token to ~/.config/nca/config.json. After that, all other nca commands work.
Rules to follow:
- Ask for the minimum scopes the task needs, not "everything". Each grant replaces the previous one — if you already have
channels:read and now need channels:edit, run nca login --poll --scopes channels:read,channels:edit. Dropping a previously approved scope deactivates it.
--for-agent defaults to $NCA_AGENT_ID. You only need to pass it explicitly if you're acting for a different agent (rare).
- Never print the token, never print the config file. Post the consent URL only.
Scope catalog
<resource>:read and <resource>:edit for: agents, agent-runtimes, channels, automations, chat, model-providers, model-config, secrets, skills, backups, terminal, files, byo-providers. Plus usage:read (no :edit).
If a request returns 401 token missing scope: one of [foo:edit], the user hasn't granted that scope. Run nca login --poll again with the missing scope added to the existing list. 403 means the agent doesn't own that resource — that's a different problem; don't try to fix it with more scopes.
Local (browser/headless)
If the user has a browser: nca login. The CLI starts a local HTTP listener on a random loopback port, opens the consent page, and captures the auth code on the redirect.
If the user has no browser (SSH, dev container, CI): nca login --no-launch-browser. The CLI prints a URL and waits on stdin for the auth code. If stdin isn't a TTY either, fall back to --auth-code <code> after the user gets the code manually.
Resource recipes
The CLI prints results as JSON (channels, runtime detail) or formatted lines (lists). When the user asks "what do I have", list/ls is almost always the right starting point.
Agents (nca agent)
nca agent list
nca agent logs <agentId>
nca agent create <name> --framework <fw> ...
framework is claude-code (default), codex, or gemini-cli. Each framework needs different credentials — pick exactly one of these credential paths per create:
| Framework | Required credentials (flag or env) |
|---|
claude-code | --anthropic-auth-token or $ANTHROPIC_AUTH_TOKEN; optional --anthropic-base-url |
codex | --openai-api-key or $OPENAI_API_KEY; optional --openai-base-url |
gemini-cli | --google-api-key or $GEMINI_API_KEY / $GOOGLE_API_KEY; optional --google-gemini-base-url, --gemini-model |
Don't pass cross-framework flags — the CLI ignores them but the command shape is confusing.
Example: create a Claude Code agent named "support-bot" using a token from env
ANTHROPIC_AUTH_TOKEN=sk-ant-... nca agent create support-bot --framework claude-code
The output line is: <agentId> <name> <framework>/<runtime> <status> followed by sprite/account hints in dim text. Capture <agentId> for follow-up commands.
Agent runtimes (nca runtime)
A runtime is the sprite (or k8s pod) that runs the agent. Today one agent = one runtime, but the runtime is the thing you delete to tear down the sprite.
nca runtime list
nca runtime get <runtimeId>
nca runtime delete <runtimeId>
runtime delete is destructive and cascades to the agent(s) attached to the runtime. Don't run it without explicit user confirmation. The web UI has a confirm dialog; the CLI does not.
Channels (nca channels) — the new subtree from PLAN-02
Channels are the inbound/outbound message providers (Telegram bot, Lark bot, Slack app, Discord, Matrix, plus a fake provider for testing). Each channel belongs to exactly one agent.
nca channels list
nca channels get <channelId>
nca channels create --provider <p> --label <l> --config <json>
nca channels update <channelId> [--label …] [--status …] [--config …] [--credentials …]
nca channels delete <channelId>
nca channels test <channelId>
nca channels register <channelId>
--agent-id defaults to $NCA_AGENT_ID for create. If it's not set, always pass --agent-id explicitly — the CLI errors with "agent id is required" otherwise. For list, --agent-id is a client-side filter only.
--config and --credentials accept either inline JSON or @path/to/file.json. Use @file paths whenever the JSON is more than a couple of fields — argv string-escaping rules will betray you otherwise. Always put credentials in a file, not on the command line, so the token never lands in shell history.
The output of get and update masks any sensitive field (credentials, credentialsCiphertext, …) to [redacted]. If a printed channel still shows credentials, treat that as a bug and stop.
Example: wire up a Telegram bot
cat > /tmp/tg-config.json <<'EOF'
{ "webhookSecret": "..." }
EOF
cat > /tmp/tg-creds.json <<'EOF'
{ "botToken": "123456:ABC-DEF..." }
EOF
nca channels create \
--provider telegram \
--label "Support inbox" \
--config @/tmp/tg-config.json \
--credentials @/tmp/tg-creds.json
nca channels register <channelId>
nca channels test <channelId>
rm /tmp/tg-creds.json
Status values: draft (created but inactive), active, paused, error. Use nca channels update <id> --status paused to disable a channel without deleting it.
Local daemon (nca daemon)
nca daemon only matters when the user wants to host agents on their own laptop (vs. on sprites). It registers the laptop with the API, then a long-running process accepts WebSocket commands from the API.
nca daemon register --token ldt_<from-web-ui> [--name <hostname>]
nca daemon start
nca daemon status
nca daemon stop
nca daemon logs
nca daemon doctor
The ldt_… token comes from the web UI at Settings → Local Daemons. It must start with ldt_. After register succeeds, ~/.config/nca/daemon.json holds the config; like the regular token, don't print it.
If daemon doctor flags a framework as missing, install the matching CLI locally (claude, codex, gemini) and re-run.
Common failure modes
| Symptom | Fix |
|---|
agent id is required: pass --agent-id, set $NCA_AGENT_ID, or use the global --agent-id option | You're outside a sprite. Pass --agent-id <id> or export NCA_AGENT_ID=.... |
401 token missing scope: one of [foo:edit] | Run nca login --poll --scopes <existing>,foo:edit. Keep prior scopes; new grant replaces old. |
403 from a resource endpoint | Token's user does not own the resource — different problem from scopes. Don't re-grant. |
--poll requires --scopes | Add --scopes <list>. --poll mode is for agents only. |
--for-agent or NCA_AGENT_ID is required for --poll | You're not in a sprite. Pass --for-agent <agentId> explicitly. |
nca login works but the next command says "not authenticated" | Different --api-url? Or a different $NCA_CONFIG_DIR? The login config is per-API-URL implicit; switching API URL silently uses a stale token. Re-login. |
nca agent logs prints a TODO | Not implemented in 0.4.0. Use the web UI or nca runtime get <id> for status. |
What this CLI does not do (in 0.4.0)
The API exposes more than the CLI. If the user asks for something not in this list, fall back to raw HTTP — see references/raw-http.md.
Not in CLI: automations, skills, model-providers, model-config, byo-providers, secrets, files, backups, terminal, usage, chat.
For these, the pattern is:
TOKEN=$(jq -r .token ~/.config/nca/config.json)
curl -fsS -X GET "$NCA_API_URL/automations" \
-H "Authorization: Bearer $TOKEN" | jq
The same scope rules apply — if you get 401 token missing scope, re-run nca login --poll with the right scope added.
Safety rules
These aren't suggestions; the user's data depends on them.
- Never print
~/.config/nca/config.json, ~/.config/nca/daemon.json, or $NCA_TOKEN. Their content is a bearer credential. Posting it in chat exposes it to the user and the chat backend.
- Post only the consent URL that
nca login --poll prints. The URL alone is safe — opening it without approving doesn't grant anything.
- Ask for the minimum scopes.
channels:edit to create a channel, not secrets:edit. New grants replace the old grant; over-asking shrinks the user's trust budget.
runtime delete and agent deletions cascade. Confirm with the user, even if they've already approved agent-runtimes:edit.
- Channel credentials go in
@file, not inline. Inline strings land in shell history and process listings.
- Trust the redaction. If
nca channels get prints something that looks like a real credential where [redacted] should be, stop and report it; don't keep going.
Pointers
references/raw-http.md — patterns for the resources without CLI coverage.
apps/cli/src/commands/ (in the repo) — authoritative source if a flag isn't behaving as documented.
- Cloud Agents API docs:
https://docs.netmind.xyz/.