Docs · Reference
selan CLI reference
Every command, every environment variable, every error message, and what differs on Windows. For how it all fits together, start at the docs.
Which commands does selan have?
| Command | What it does |
|---|---|
selan login |
Signs you in through the browser, with Google or Microsoft. Over SSH it prints a URL to paste. It does not need a terminal, so selan login > log 2>&1 works. |
selan logout |
Revokes the session server-side, then deletes the local file. If revocation fails it warns and still deletes: an offline user must not be stuck signed in. |
selan whoami |
Who you are signed in as and which company. With an API token set, names the token and the address it spends as, showing only its last four characters. |
selan claude [args…] |
The main command. Every argument passes through verbatim, including -p and --resume. Signs you in automatically if you have no session. |
selan claude --model provider:model |
Runs the session on your company's own provider key. A value with no colon is Claude Code's own flag and passes through untouched. |
selan run name |
Launches a name declared in .selanrc.json at the repository root, expanded to the words it stands for before anything else reads them. Bare, it lists what the file declares and launches nothing. See Declared launches. |
selan codex [args…] |
Launches Codex on the company's connection rather than your own ChatGPT. Every argument passes through, codex exec included. Codex itself must be installed. See Codex. |
selan codex --model provider:model |
Pins that session to one provider's copy of the model. Without a provider in front, the name means the model itself and Selan falls through your company's accounts in order. |
selan usage |
Your company's rate-limit headroom and your own spend budget. The statusline shows the same numbers. |
selan feature [enable|disable name] |
Turns a feature on or off for this machine, from your next session. This machine's choice outranks your company's setting, either way. Bare, it lists each feature, what it does and what this machine asks for: context-editing drops old tool output a long session no longer needs, and context-editing-inputs drops the arguments old tool calls were made with. tool-search loads MCP tool definitions only when a session uses them, rather than every tool's full schema on every request. Your company has no setting for it: it is on unless this machine turns it off, and an ENABLE_TOOL_SEARCH you export yourself wins either way. |
selan version |
This build, and the latest release on its channel. |
selan update |
Fetches and runs the installer again, replacing the binary in place. Refuses on a local build. |
seland [args…] |
The same binary, launching Claude Code with --dangerously-skip-permissions after one enter to confirm, skipped when piped or in CI. Only claude, codex and run are read as subcommands; every other argument belongs to the agent. See seland. |
seland codex [args…] |
The same for Codex: its approval prompts and its sandbox both off, after the same enter, skipped when piped or in CI. -s keeps the sandbox you name and turns off only the prompts; -a skips nothing. See running without prompts. |
selan itself takes --version and --help, and
a bare --model is treated as selan claude --model.
Everything after claude is Claude Code's.
run is Selan's under both names, so a prompt cannot begin with it. Everything
after codex is Codex's.
How do I save a launch for a repository?
A launch you type every day is worth writing down once. Put the ones a repository
has in .selanrc.json at its root, and they come with the checkout rather
than living in somebody's shell history.
{
"agents": {
"reviews": {
"agent": "code-review"
},
"oncall": {
"agent": "incident-triage",
"ask": false
}
}
}
selan run reviews
# → selan claude --agent code-review
selan run oncall
# → selan claude --agent incident-triage --disallowedTools AskUserQuestion
selan run
# lists what the file declares, and launches nothing
The file says which agent. .claude/agents/ says what that agent
is, so there is no model field here: the agent definition owns that, and a second
place to write it is a second place for it to disagree. Anything you type after the
name is kept and kept last, so selan run reviews --model openrouter:…
works and the file stays a set of names rather than a cage.
A field it does not recognise is refused rather than ignored. A name that quietly is not what it reads like is worse than one that will not start, so a misspelt key says so at the terminal.
"ask": false is for the agent you want to decide rather than
consult you. It takes Claude Code's AskUserQuestion tool away, so
the agent cannot stop to put a question to you; an agent that cannot ask says in its
final answer what it could not decide. Permission prompts are not questions and still
come, which is what seland is for.
A name whose agent does not exist is refused before launching. Both
places Claude Code reads one from are checked, .claude/agents/ beside the
file and the same under your home directory, matched on the frontmatter's
name: the way Claude Code matches it. Without that you would get Claude
Code's list of its own built-in agents, which says nothing about the file that named
yours.
seland run reviews is the same declared launch with permission checks
off. There is no field for this in the file on purpose. Unlike ask, it
widens what the session may do rather than narrowing it, and that is a decision to
make at the terminal rather than one a committed file makes for everyone.
Which environment variables does selan read?
| Variable | Effect |
|---|---|
SELAN_TOKEN |
An API token minted by an owner. Skips sign-in entirely, so no credential is written to disk. Beats a stored login: with this set, you spend as the token. It is not a no-write mode: selan still keeps its update check and usage cache under ~/.selan, and still updates itself. In CI, set SELAN_NO_AUTO_UPDATE too. See Running unattended. |
SELAN_INSTALL_DIR |
Where the installer puts the binary. Defaults to /usr/local/bin, or %LOCALAPPDATA%\Programs\selan on Windows. |
SELAN_NO_AUTO_UPDATE |
Stops selan claude installing a newer release before it launches. Counts as set whatever its value, including 0. |
SELAN_NO_STATUSLINE |
Stops Selan installing its statusline. Counts as set whatever its value. |
ANTHROPIC_BETAS |
Not a Selan variable, but it interacts. Selan sets the 1M-context beta unless you have already set this yourself. See the warning below. |
ANTHROPIC_BETAS yourself silently costs you the 1M
context window. Selan's value is a default, not a merge: any existing value wins outright
and you drop to 200k with no warning. If you need another beta, include
context-1m-2025-08-07 alongside it.
The window also depends on what serves the request. On a subscription account the 1M beta is removed before the request goes upstream, because the plan does not carry it, so that request runs at 200k whatever you set. An API key does carry it.
What does this error message mean?
| What you see | What it means |
|---|---|
.selanrc.json: json: unknown field … |
A key the file's format does not have, named in the message. Refused rather than ignored, because a launch that quietly is not what it reads like is worse than one that will not start. |
.selanrc.json: … names the agent … |
The agent an entry names has no definition beside the checkout or under your home directory. Both .claude/agents/ directories are searched, matched on the frontmatter's name:. See Declared launches. |
.selanrc.json declares no … |
That name is not in the file. selan run with no name lists what is. |
codex not found on PATH |
Codex itself is not installed. Selan launches it, it does not bundle it. See Codex. |
no active session |
Your session expired or was revoked. Run selan login. |
spend limit |
A budget was reached, either yours or the workspace's. The message says which and when it lifts. Retrying does not clear it. |
not an available … model |
The provider does not offer that model, or your company has not enabled it. The message lists what is available. |
your company has not connected … |
You named a provider your company has no key for. Drop the --model prefix, or ask an owner to connect it. |
model_not_allowed |
You picked a model from /model that your company has since switched off. Pick another and relaunch: the list is only read at startup. |
too many concurrent requests |
You have several Claude Code sessions in flight. Finish or close one. |
no capacity |
Nothing in your company's pool could take the request. If every account is busy with other requests, retrying shortly works. If every subscription seat has used up its 5-hour or weekly window and no API key serves the model, nothing frees until a window resets, and the error does not say when: selan usage and the statusline do. Until then, pick a model on another provider, or ask an owner to connect an API key. |
could not lease a credential |
A Selan service is unreachable. It is not a refusal, so retry. If you are on an API token, this is also what an identity lookup failure reports. |
a malformed SELAN_TOKEN |
Checked locally before any request, so a typo is reported as a typo and not as a revoked token. A real token starts selanct_. |
Errors from a provider are passed through untouched, with one exception. A
529, which means the provider itself is overloaded, is answered as a
503 in our own words: it is the one case where the provider's body is
replaced rather than relayed. If the model itself refuses something, you see its
words, not ours.
What differs on Windows, macOS and Linux?
| macOS · Linux | Windows | |
|---|---|---|
| Install | curl … install.sh | sh |
irm … install.ps1 | iex, PowerShell 5.1 or newer |
| Default location | /usr/local/bin |
%LOCALAPPDATA%\Programs\selan |
| Session file | ~/.selan/credentials.json, mode 0600 |
%USERPROFILE%\.selan\credentials.json |
| Also written | ~/.selan/version-check.json, usage-cache.json, and claude-settings.json, which carries the same session token so it is not passed on a command line where ps would show it. selan codex writes a fenced block in ~/.codex/config.toml, and your company's connectors are added to ~/.claude.json. |
The same files under %USERPROFILE% |
seland |
A symlink to the same binary | seland.exe, a copy of the binary (a symlink needs Developer Mode) |
| Exit code | Claude Code's, inherited | Claude Code's, passed through |
seland is the same binary under a second name, which the installer puts
beside selan. Running it is
selan claude --dangerously-skip-permissions. See
seland. How it gets there is the only thing
that differs by platform; what it does is identical.
Inside WSL, use the Linux installer: a WSL session is Linux. Claude Code has to be installed inside WSL too.
%NAME% inside an argument is expanded.
claude is usually a batch file, which cmd.exe parses,
and cmd.exe expands environment variables even inside quotes. There is no
escape for a literal %. If a prompt needs one, put it in a file and point
Claude Code at the file.
What reaches Selan?
Requests go to the Selan proxy, which leases one of your company's credentials per
request and streams the response straight back. Prompts are not stored. What Selan
records is metering: token counts, model, cost and who made the request. A
repository slug is recorded only when the caller supplies x-selan-repo
(the Selan CLI does this automatically) and your company has turned Repository
attribution on. Selan consumes the header and never sends it to the model provider.
No Anthropic credential is ever on your machine. The only secret Selan puts there is a
revocable session token, and selan logout revokes it.
It works the other way too: if you have your own ANTHROPIC_API_KEY
exported, Selan removes it before launching Claude Code. Your personal
key is not sent to Selan and then ignored. It never leaves the machine.
See Privacy for the full picture, including what our own processors see.