The old README was a feature list. For a crypto CLI the first question is not "what can it do" but "what can it do to me", so the rewrite answers that on the first screen: four commands, 258 lines, one dependency, never signs anything. README ------ - Centred header with .github/banner.svg (new) and badges that are all facts checkable from the repo: TypeScript 7.0, Node >=22.12, commander 15, one dependency, 258 source lines, the API host, "signs transactions: never", and one red badge admitting `pnpm dev` is broken on TS 7. - "What this is" explains the whole architecture in a paragraph — commander parses, built-in fetch requests, print, exit — and points at src/api.ts and src/commands/ as the complete audit surface. - The agent section says plainly what the key can and cannot do: it can build a buy, it cannot broadcast one. The signing rails and their three-layer allowlist live in the backend and stay there. - Commands are now one section each with real sample output, the endpoint each one calls, and whether it needs a key, instead of a flag table. - Install says outright there is no npm package and it builds from source, ending on `vectr price` because a keyless answer proves the network path. Uninstall notes the key stays in ~/.vectr/config.json until deleted. Node floor: 18 -> 22.12 ----------------------- The README and `engines` both claimed Node 18 "because the CLI uses built-in fetch". Wrong reason and wrong number: the real floor is the commander dependency, which is ESM-only and needs 22.12. Someone on 18 would have installed, built, and hit a module error with the docs telling them their runtime was fine. Both now say >=22.12, and the website renders the same number from src/lib/tooling.ts. agent: tell the truth about where an unsigned transaction can go ---------------------------------------------------------------- The transaction block ended with "Sign this transaction in the Vectr terminal", which reads as though the Terminal is the only way to use it and as though the CLI handed something over. Neither is true: the transaction is unsigned and it is the owner's, submittable from any wallet. Now: "Not signed. Submit it from your wallet, or ask the same thing in the Vectr Terminal to confirm it there." Also added pnpm-workspace.yaml with the @types/node release-age exclusion, and bumped @types/node 25.9.1 -> 26.6.5. |
||
|---|---|---|
| .github | ||
| src | ||
| .gitignore | ||
| LICENSE | ||
| package.json | ||
| pnpm-lock.yaml | ||
| pnpm-workspace.yaml | ||
| README.md | ||
| tsconfig.json | ||
vectr-cli
Four commands, 258 lines, one dependency. Prices, token lists and the Vectr agent from a shell. It never signs anything, which is the nicest thing you can say about a crypto CLI.
What this is
A thin HTTP client over the public Vectr API, the same one the website uses. commander parses the arguments, Node's built-in fetch makes the request, the result is printed, the process exits. Every request it can make is in src/api.ts and the four files under src/commands/. There is nothing to audit that takes longer than a coffee.
The agent command is the one that matters. It sends a prompt to POST /agent/job, polls GET /agent/job/:id every 1.5 s, and prints the answer. If the answer is a transaction, the CLI prints what it is and tells you to go sign it in the Terminal. The key you give it can build a buy; it cannot broadcast one. The signing rails and their three-layer allowlist are in the backend and stay there.
Install
There is no npm package. It builds from source:
git clone https://git.vectr.bot/vectr/cli.git vectr-cli
cd vectr-cli
pnpm install
pnpm build
npm link # puts `vectr` on PATH
vectr price # keyless, so an answer proves the network path
Node 22.12 or newer: the commander dependency is ESM-only and needs it. Update with git pull && pnpm install && pnpm build. Uninstall with npm unlink -g @vectr/cli; your key stays in ~/.vectr/config.json until you delete it.
Commands
vectr login --key vectr_... [--url <api>]
Writes the key (and optionally a backend URL) to ~/.vectr/config.json. Keys are made at vectr.bot/profile?tab=api-keys, where read-only, read-write, IP and recipient restrictions are set at creation and cannot be widened afterwards. The CLI checks that the key starts with vectr_ and nothing else; the backend does the rest.
vectr price
ETH $2775.87
GET /price/native. The symbol comes from the backend, so the same binary prints whatever the deployment's gas coin is. No key.
vectr tokens [-n 10] [--search <q>]
Top tokens by market cap as a fixed-width table, or a name and symbol search. Price is USD; graduated tokens get a tag. GET /tokens?limit= or GET /tokens/search?q=. No key.
vectr agent "<prompt>" [--json] [--model <id>]
vectr agent "what tokens are trending?"
vectr agent "what did my launches earn this week"
vectr agent "build a 0.01 ETH buy of the top token"
vectr agent "top 3 by mcap" --json | jq -r .response
Prints Thinking and a dot every 600 ms until the job settles. --json dumps the raw job (status, response, richData); without it you get the response text and, if the agent built a transaction, a --- Transaction --- block with the action and details and a pointer to vectr.bot/terminal to confirm it. --model passes a model id through to the backend's catalog. Each turn is billed against the key owner's credit balance.
Exit code 1 on a failed job, an API error, or a missing key. Errors go to stderr.
Configuration
~/.vectr/config.json:
{ "apiKey": "vectr_...", "apiUrl": "https://api.vectr.bot" }
VECTR_API_KEY and VECTR_API_URL are read only when the file does not set that field. The file wins. If you once ran vectr login --url https://some-dev-host and that host is gone, no environment variable will save you; edit the file. Ask how we know.
Scripting
Non-zero exit and stderr on failure, so it chains and crons:
0 * * * * vectr price >> ~/vectr-price.log 2>&1
vectr tokens -n 50 > snapshot.txt
vectr agent "top 3 by mcap" --json | jq -r .response
For anything the four commands don't do, call the API. The CLI is a formatter, not a client library.
Development
pnpm build # tsc -> dist/, CommonJS, ES2020
node dist/index.js price
pnpm dev is ts-node src/index.ts and it does not run. TypeScript 7 removed the JS compiler API ts-node loads (Cannot read properties of undefined (reading 'fileExists')). Build and run dist/ instead; the build takes about a second.
The version string is hard-coded as 1.0.0 in src/index.ts, separately from package.json. They agree today.
Layout
src/
index.ts commander program, four subcommands
api.ts getApiClient(): config + env resolution, get/post with X-API-Key
config.ts ~/.vectr/config.json read and write
commands/
login.ts
agent.ts job submit, poll, print, transaction block
price.ts
tokens.ts
dist/ tsc output, gitignored, what `bin` points at
Skeletons in the closet
- Six of the seven source files start with a UTF-8 byte-order mark.
tscstrips it, so the shebang indist/index.jssurvives and the binary runs; the diffs just look haunted. pnpm devhas been dead since the TypeScript 7 bump in commit5775f08. The script is still inpackage.json, and the old README told you to use it.--modelsuggestsclaude-opus-4-7in its help text. The backend's default isclaude-sonnet-5, and it has a catalog of nine. The help text picked a favourite and never updated it.process.exit()ingetApiClientis a deliberateprocess.exitCode = 1followed by a bareprocess.exit(), becauseprocess.exit(1)tripped a libuv assertion on Windows. Commit4090f75has the story. Every other error path setsexitCodeand returns.- The agent poll has no timeout. A job that never settles is a CLI that never exits. Ctrl+C is the timeout.
License
MIT. Says so in three places and they all agree, which is more than the other repos manage.