Command-Line Tool (CLI)#
The project ships with a cli/ directory — a ready-to-use command-line program. Once your users log in with their own API key, they can call your platform API as themselves, right from the terminal.
By default it's called stackflare, but the whole command name is configurable — change one environment variable and it becomes your own brand (e.g. acme, mytool), then package it as a single file to ship to users. This page covers how to use it and how to rebrand it as your own.
1. Run it#
The CLI is written with Bun. During development you just run the source with Bun — no build needed.
bashcd cli
bun install # first time
bun run start help # show help
Common commands:
bashbun run start login # log in (paste an API key)
bun run start whoami # show the current identity
bun run start logout # log out
In development it automatically reads the config from the project root
.env, so changes to.envtake effect immediately — no rebuild required.
2. Rebrand it as your own ⭐#
The command name and service URL both come from the project root .env — no code changes needed.
Open .env and set these two variables:
bash# Your platform URL (where the CLI calls the API)
PUBLIC_APP_URL=https://your-app.com
# Your command / brand name (defaults to stackflare)
PUBLIC_CLI_NAME=acme
After that:
- Running
bun run start helpshowsacmeas the command name - The built binary filename is also
acme - Users type
acme login,acme whoami, etc.
PUBLIC_CLI_NAMEkeeps only letters, digits and._-; other characters are stripped so it's safe as a command and filename.
How it resolves#
You don't need to know this to use it, but the priority order (high to low) is:
- The value baked into the binary at build time (no
.envneeded after distribution) - The live value of
PUBLIC_CLI_NAME/PUBLIC_APP_URLin.envwhen run from source - Otherwise → command name defaults to
stackflare; an empty URL makes login error out
So: editing .env takes effect instantly in dev; a built binary uses whatever was baked in. Remember to rebuild after rebranding, then distribute.
3. Build & distribute#
The build output is a single-file executable — users download and run it, with no Bun or Node required.
bashcd cli
bun run build # current platform only, output in dist/<your-name>
bun run build:all # build all 5 platforms at once
build:all output (assuming PUBLIC_CLI_NAME=acme):
| Platform | Filename |
|---|---|
| macOS (Apple Silicon M1/M2…) | dist/acme-darwin-arm64 |
| macOS (Intel) | dist/acme-darwin-x64 |
| Linux (x64) | dist/acme-linux-x64 |
| Linux (ARM) | dist/acme-linux-arm64 |
| Windows | dist/acme-windows-x64.exe |
Upload the right file to your download page / GitHub Release and share it with users.
Build a different brand on the fly#
If you don't want to edit .env, override via environment variables for a single build:
bashPUBLIC_CLI_NAME=acme PUBLIC_APP_URL=https://acme.com bun run build
4. How users use it (share this with them)#
- In your dashboard, go to Developer → API Keys and create a key starting with
sk_live_ - Download the CLI for their system, make it executable and put it on PATH:
bashchmod +x acme-darwin-arm64 sudo mv acme-darwin-arm64 /usr/local/bin/acme - Log in:
bashacme login # paste the key acme login --key sk_live_xxx # or pass inline in a script - The key is saved to
~/.acme/config.json(permission 600, owner-only)
For the full end-user install & usage guide, see API Keys & CLI.
5. Want to add a command?#
The CLI code is short — just 4 files under cli/src/:
| File | Role |
|---|---|
index.ts | Command entry & dispatch (add a case here) |
config.ts | Local key storage, API URL resolution |
constants.ts | Command name / URL resolution |
api.ts | Backend request wrapper |
Add a case in the switch in index.ts and implement the function:
tsasync function cmdPing() {
const config = await loadConfig()
if (!config.key) {
console.error(c.red(`Not logged in. Run: ${CLI_NAME} login`))
process.exit(1)
}
const apiUrl = resolveApiUrl(config)
const res = await request(apiUrl, "/v1/your-endpoint", { key: config.key })
console.log(res)
}
// Register the command
case "ping":
return cmdPing()
Create the matching backend endpoint under src/routes/v1/, validating the key with requireUserApiKey (see api-keys/verify.ts).