Auth layer for AI CLIs. One import, any provider.
import { auth } from "@byorouter/auth"
await auth.ensureEnv("openai")
// OPENAI_API_KEY is now set
const openai = new OpenAI() // just worksEvery AI CLI and local tool re-implements the same auth boilerplate:
- OAuth flows (PKCE, callback servers)
- API key prompts
- Credential storage
- Token refresh
- Provider-specific quirks
@byorouter/auth handles all of it so your tool doesn't have to. Existing SDK code works without changes.
npm install @byorouter/authimport { auth } from "@byorouter/auth"
// Authenticate and set env vars — existing SDKs work without changes
await auth.ensureEnv("openai")
await auth.ensureEnv("anthropic")
// Use SDKs as normal
const openai = new OpenAI()
const anthropic = new Anthropic()ensureEnv resolves credentials in this order:
- Existing environment variable (e.g.,
OPENAI_API_KEY) - Stored credentials in
~/.byorouter/credentials.json .envfile in the current directory- Interactive login (browser OAuth or terminal prompt)
If a credential already exists, no login is triggered.
Most tools only need ensureEnv. The rest provide finer control.
| Method | Purpose |
|---|---|
ensureEnv(provider) |
Ensure credential + set env var |
ensure(provider) |
Ensure credential without modifying env |
login(provider, options?) |
Force interactive login |
get(provider) |
Read stored credential (no prompts) |
check(provider) |
Check if credential exists |
logout(provider) |
Remove stored credential |
list() |
List stored providers |
path() |
Show credential storage path |
Ensure a credential exists and set the corresponding environment variable. Returns the credential.
const cred = await auth.ensureEnv("openai")
// process.env.OPENAI_API_KEY is now setEnsure a credential exists without setting env vars. Returns the credential.
const cred = await auth.ensure("openai")
// { provider: "openai", token: "sk-...", expiresAt?: Date }Force an interactive login flow, even if a credential already exists.
await auth.login("openai")
await auth.login("openai", { force: true })Get a stored credential without triggering any interactive flow. Returns null if not found.
const cred = await auth.get("openai")Check if a credential exists.
if (await auth.check("openai")) {
// ready to go
}Remove a stored credential.
await auth.logout("openai")List all stored providers.
const providers = await auth.list()
// ["openai", "anthropic"]Get the credentials file path. Useful for debugging.
auth.path()
// ~/.byorouter/credentials.json| Provider | Auth Method | Env Variable |
|---|---|---|
| OpenAI | OAuth | OPENAI_API_KEY |
| Anthropic | API Key | ANTHROPIC_API_KEY |
More providers coming soon (Google, HuggingFace, OpenRouter, Groq, Mistral, DeepSeek).
# Login to a provider
npx @byorouter/auth login openai
# Check stored credentials
npx @byorouter/auth list
# Remove a credential
npx @byorouter/auth logout openaiThe default export works out of the box. Use createAuth for custom configuration:
import { createAuth } from "@byorouter/auth"
const auth = createAuth({
store: "~/.myapp/credentials.json",
callbackPort: 9876,
providers: {
openai: {
clientId: "your-app-client-id",
}
}
})OAuth providers (OpenAI): Opens a browser, handles the PKCE flow with a local callback server, exchanges the code for credentials, and stores them locally.
API key providers (Anthropic): Checks for an existing env var, then prompts in the terminal if not found. Stores the key locally for next time.
Credentials are stored in plaintext JSON at ~/.byorouter/credentials.json, following the same approach as ~/.npmrc, ~/.aws/credentials, and ~/.config/gh/hosts.yml.
@byorouter/auth is designed for local tools and CLIs.
If you're building a hosted application where users connect their own AI accounts, check out BYORouter — secure credential delegation and an OpenAI-compatible proxy, so you never store API keys in your app.
Local tools → @byorouter/auth
Hosted apps → BYORouter
MIT