Command-line access to AIsa: one API key for
Claude, GPT, Gemini, DeepSeek, Kimi, GLM and published Tool Router
operations. Browse the public provider/endpoint catalog separately;
catalog metadata is not a substitute for schema or quote.
npm install -g @aisa-one/cli# Sign in (browser; stores OAuth tokens — no key to copy)
aisa login
# Discover published tools (Router; search/schema may be anonymous)
aisa search "company facts" --json
aisa schema get_financial_company_facts --json
# Browse the read-only provider/endpoint catalog
aisa api list
aisa api show financial
# Quote a published Router tool (does not execute)
aisa quote --input '{"calls":[{"call_id":"c1","tool":"get_financial_company_facts","arguments":{"ticker":"AAPL"}}]}' --jsonaisa login opens a browser, signs you in, and stores OAuth tokens. You do not
need to create or paste a key from the console. For CI or scripts, set
AISA_API_KEY or run aisa login --key <key>. New accounts receive $5 in
free credits.
This first block does not run aisa chat or aisa call. Quote is a price
observation, not authorization to execute. See
Published tools for the quote/approval
contract before a billable call.
Root help lists 21 explicit commands plus implicit help. Removed domain
shortcuts and raw execution names are unknown commands — not aliases and
not forwarded to aisa call.
These four commands are a thin HTTP client for the same Router service MCP uses. They do not search the local catalog cache and do not call providers directly.
| CLI | MCP identifier | POST path |
|---|---|---|
aisa search |
AISA_SEARCH_TOOL |
/v1/tool-router/aisa-search-tool |
aisa schema |
AISA_BATCH_GET_SCHEMA |
/v1/tool-router/aisa-batch-get-schema |
aisa quote |
AISA_BATCH_QUOTE |
/v1/tool-router/aisa-batch-quote |
aisa call |
AISA_BATCH_USE |
/v1/tool-router/aisa-batch-use |
--json prints the unmodified application body (MCP identifiers stay).
Human output maps only those four identifiers onto CLI names. aisa manifest
and aisa manifest search / schema / quote / call expose mcp, auth,
enforced, safety, exits, and parseable examples.
Recommended sequence: discover a tool → aisa schema when
has_full_schema=false → aisa quote → aisa call. Quote and call share
one request shape. Enforced: invalid local input exits 2 and is not sent;
quote and call refuse to run without an OAuth session or static AIsa API key. Not
enforced: the CLI does not record quotes, approvals, or budget caps and
does not reject an unquoted call. Instruction: do not execute unquoted
calls; the caller must ensure a matching quote and approval. Quote is a
price observation, not authorization. A data request or credentials alone is
not spending approval. Do not invent tool names or guess required values.
aisa call is billable. A missing or failed quote is never free. Estimated
cost is not a limit. If a hard monetary cap is required, do not execute
calls with no guaranteed maximum. A partial quote is not a full-batch total;
call only an independently approved successful subset, and do not silently
retry. Without an OAuth session or static AIsa API key, do not invent a business result.
--input is inline JSON (no file required). Documented shell examples use
POSIX single quotes so apostrophes, Unicode, $(), and backticks stay
literal.
get_financial_company_facts is a published tool whose schema includes
ticker. Do not invent unpublished tool names. Router search does not
guarantee every former domain-shortcut function.
aisa search "company facts" --json
aisa search --input '{"query":"company facts","limit":5}' --json
aisa search --input '{"query":"company facts","known_fields":{"name":"O'\''Reilly — 苹果"}}' --json
aisa search -f request.json --json
aisa search -f - --json < request.json
aisa schema get_financial_company_facts --json
aisa schema --input '{"tools":["get_financial_company_facts"]}' --json
aisa quote --input '{"calls":[{"call_id":"c1","tool":"get_financial_company_facts","arguments":{"ticker":"AAPL"}}]}' --json
aisa quote -f request.json --json
aisa call --input '{"calls":[{"call_id":"c1","tool":"get_financial_company_facts","arguments":{"ticker":"AAPL"}}]}' --json
aisa call -f - --json < request.json--json keeps large integer tokens. Diagnostics go to stderr. Exit 2 means
local input was invalid and nothing was sent; 1 is transport, auth, or an
HTTP error; 3 means the Router returned a batch with at least one failed
item.
search and schema may be anonymous. quote and call require a
stored OAuth session or static API key. aisa login stores access and refresh
tokens in ~/.aisa/tokens.json (0600), along with the OAuth client ID and
expiresAt (Unix milliseconds). Access tokens refresh within 60 seconds of
expiry; a 401 triggers one refresh and retry. AISA_API_KEY takes precedence
and never refreshes. Legacy ~/.aisa/key files migrate on first read; conf
apiKey is a write-only compatibility mirror.
For CI, set AISA_API_KEY or use aisa login --key <key>. The default Router
origin is https://tools.aisa.one (independent of baseUrl /
https://api.aisa.one). Point a test Router at AISA_ROUTER_BASE_URL (origin
or prefix before /v1/tool-router/...), or aisa config set routerUrl. There
is no origin fallback.
quote never executes. Router requests do not follow HTTP redirects, so a
307/308 cannot turn quote into call. There is no automatic quote-to-call sequence and no
retry.
api list and api show are the supported read-only catalog. They browse
public provider and endpoint metadata (--json, --refresh, --health,
--category, path filters). They are not deprecated and are not Router
search / schema. Catalog paths and prices are browsing metadata, not a
substitute for schema or quote, and not a way to execute an endpoint.
aisa api list # all catalog providers
aisa api list --category finance # finance, search, social, productivity, other
aisa api list --health # include provider health
aisa api show financial # endpoints in one provider
aisa api show financial /news # one endpoint: params and catalog price
aisa api show dataforseo --all # long lists truncate to 40 by defaultA provider id is not always its URL slug — brave-search serves
/apis/v1/brave/..., and api show prints the catalog path. The catalog
reports every method as GET; treat that as advisory.
The catalog is cached in ~/.aisa/cache (override with AISA_CACHE_DIR). Pass
--refresh to any command to bypass it, or aisa cache clear.
GPT, Claude, Gemini, DeepSeek, Kimi, GLM, Qwen and the rest behind one OpenAI-compatible endpoint.
aisa chat "your message" --model gpt-4.1-mini
aisa chat "explain this" --model claude-opus-4-6
aisa chat "respond in JSON" --model gemini-2.5-pro --json
echo "summarize this" | aisa chat # pipe support
aisa models # list all models
aisa models --provider anthropic # filter by provider
aisa models show gpt-4.1-mini # model detailsStreaming is on by default; pass --no-stream to disable it.
aisa balance # wallet and API key credit balance
aisa balance --json
aisa topup # open the console billing page to add credit
aisa topup 20 # same, deep-linked to $20Payment always finishes in the browser: card details belong to Stripe's hosted
page, not to us, and a bank's 3-D Secure step needs one. topup opens the
right page; --no-open prints the URL instead.
aisa usage is not available yet — the gateway does not serve
GET /v1/credits/usage (it 404s, while /v1/credits/balance on the same route
group works). Use the console for usage history
in the meantime.
Skills are markdown files that teach AI coding agents (Claude Code, Cursor, Copilot, …) how to use AIsa. They come from the agent-skills repository.
aisa skills list # all skills
aisa skills list --category financial # one category
aisa skills search "financial analysis"
aisa skills show marketpulse # bare name or financial/marketpulse
aisa skills install marketpulse # install to detected agent directories
aisa skills install marketpulse --force # replace whatever occupies that directory
aisa skills remove marketpulseInstalling replaces the target directory rather than merging into it, so a
previous skill's scripts and assets cannot linger and keep being loaded, and a
partial download aborts without touching what is already there. Each install
writes a small .aisa-skill.json recording which skill owns the directory —
that marker is what lets the CLI tell two same-named skills apart.
Naming a category (financial/marketpulse) means "this specific skill", so the
CLI checks the marker before replacing or removing anything. A directory
installed before markers existed cannot be verified that way, so those need
--force. A bare name (marketpulse) means "whatever holds that directory" and
always works — it only resolves when the leaf name is unique across the repo.
Skills install to whichever agent directories exist on your machine:
| Agent | Directory |
|---|---|
| Claude Code | ~/.claude/skills/ |
| Cursor | ~/.cursor/skills/ |
| GitHub Copilot | ~/.github/skills/ |
| Windsurf | ~/.codeium/windsurf/skills/ |
| Codex | ~/.agents/skills/ |
| Gemini | ~/.gemini/skills/ |
| OpenClaw | ~/.openclaw/skills/ |
aisa skills init my-skill # default template
aisa skills init my-skill --template finance # finance, llm, search, twitter, videoBundled templates may keep those domain labels. Their runnable steps use
search / schema / quote / call (and optional api list / api show).
They do not invent tool names or treat Router as a replacement for every
removed shortcut. The llm template stays on chat / models.
To publish a skill, open a pull request against AIsa-team/agent-skills.
npx @aisa-one/cli connectOpens a small local page (served by this process on 127.0.0.1, shut down
when finished) where you tick the AIsa MCP servers you want and the coding
agents to install them into. Claude Code is configured through its own
claude mcp add (user scope), then signed in through its own OAuth: connect
runs claude mcp login per server, your browser opens the AIsa
authorization, and the tokens live in Claude Code's own store where it also
refreshes them — no API key, nothing pasted. Cursor, Claude Desktop and
Windsurf get config entries and run the same OAuth themselves on first use.
The page matches the AIsa Console style, reports authorization progress
live, and a success page with copy-paste try-it-now prompts opens when
everything is connected. No daemon stays behind. --no-open prints the URL
instead of launching a browser; --dry-run shows what would be written.
aisa mcp setup # configure the default servers for every detected client
aisa mcp setup --all # every live server, not just the defaults
aisa mcp setup --agent cursor # one client only
aisa mcp status # list entries and ping each configured endpointsetup reads the platform's discovery manifest (aisa.one/.well-known/mcp.json)
at run time and writes one entry per live server, in the shape each client
executes: a url entry for Cursor, an npx mcp-remote stdio bridge for
Claude Desktop and Windsurf. With an API key configured the entries carry it
as a Bearer header; without one they carry no credentials and the server's
OAuth flow opens in your browser on first use. A config file that exists but
does not parse is never overwritten. The docs-search MCP is always included
as aisa-docs.
# zsh
aisa completion zsh > "${fpath[1]}/_aisa" # then restart your shell
# or, without touching fpath:
echo 'eval "$(aisa completion zsh)"' >> ~/.zshrc
# bash
aisa completion bash > /usr/local/etc/bash_completion.d/aisa
# or:
echo 'eval "$(aisa completion bash)"' >> ~/.bashrc
# fish
aisa completion fish > ~/.config/fish/completions/aisa.fishaisa completion with no argument detects your shell from $SHELL.
Completion covers commands, subcommands, and options, plus values pulled from the local cache:
aisa api show <TAB> → provider ids
aisa api list --category <TAB> → finance, search, social, productivity, other
aisa skills show <TAB> → skill names
aisa chat --model <TAB> → model ids
The cache-backed suggestions only appear once the relevant command has been run
at least once — completion never makes a network request, so a cold cache
completes commands and flags but no dynamic values. Run aisa api list,
aisa models, and aisa skills list once to warm everything up.
aisa config set defaultModel claude-opus-4-6
aisa config get defaultModel
aisa config list # also shows derived base URLs
aisa config resetSettings:
defaultModel— default model foraisa chat(default:gpt-4.1-mini)baseUrl— platform root; the LLM (/v1), integration (/apis/v1), and catalog bases are all derived from itrouterUrl— Tool Router origin (defaulthttps://tools.aisa.one, independent ofbaseUrl); overridden byAISA_ROUTER_BASE_URLoutputFormat—textorjson
aisa login stores OAuth credentials in ~/.aisa/tokens.json.
aisa login --key <key> stores a static credential without refresh metadata.
Legacy mirrors contain the current access token; older CLIs cannot refresh it.
Third-party client configurations written by aisa connect also contain a
snapshot of the credential, not a refresh-capable OAuth session.
Environment variables:
AISA_API_KEY takes precedence over the stored key.
AISA_ROUTER_BASE_URL is the Router origin/prefix before
/v1/tool-router/... and overrides the default https://tools.aisa.one.
AISA_CACHE_DIR relocates the cache. GITHUB_TOKEN
raises the GitHub rate limit for skills commands.
git clone https://github.com/AIsa-team/cli.git
cd cli
npm install
npm run build # compile TypeScript
npm run dev # watch mode
npm test # run tests
npm run package:smoke # clean pack, isolated install, installed-bin checksRelease metadata and the exact merge/tag publish path (not an authorization
to publish) are in docs/release.md.
Three bases, one root. resolveBases() in src/api.ts derives the LLM base
(/v1), the integration base (/apis/v1), and the catalog root from a single
configured baseUrl. It tolerates a value with either suffix already attached,
because the shipped default has always included /v1 and is persisted in every
existing user's config.
The catalog's shape has three traps. endpoints[].method is hardcoded to
GET server-side. endpoint_groups[].name is an operator-entered label
(Zero, One, default) with no business meaning, which is why api show
flattens by default. And health is tracked per provider, not per endpoint, so
per-endpoint counts are one value repeated.
Parameter naming varies by endpoint. Scholar uses query, finance uses
ticker (not symbol), Twitter uses userName. aisa api show <api> <path>
prints each endpoint's description and path parameters. That listing is
catalog metadata, not an execution recipe.
MIT. See LICENSE. Copyright (c) 2026 AIsa Team.
aisa logout revokes the stored OAuth refresh token at Clerk before deleting
local credentials and compatibility mirrors. If revocation fails, it exits
with an error and retains the credentials so you can retry. Already-issued
JWT access tokens remain valid until expiry. Static API keys are only removed
locally; an AISA_API_KEY environment variable must be unset separately.
Credential reads and changes use a cross-process file lock with heartbeat and
stale-lock recovery. Re-running aisa login or switching to --key revokes
the previous stored OAuth grant before replacing it. Failed replacements
retain pending credentials in a private .pending-tokens.json recovery file;
the next login or logout cleans up those grants before completing.
If a login cannot acquire the credential lock, the newly issued grant is kept
in a private .pending-login-*.json file for the next login/logout to clean up.
Refresh persists the new credentials before optional rotation hints and legacy
mirrors; failure to save the primary token file is reported explicitly.