This explains how the SDK and CLI authenticate, where the CLI keeps your API key, and how the CLI decides which Space, key, and base URL to use.
v1 authenticates with API keys only. There is no interactive/OAuth login.
The SDK takes the key in its constructor and does not persist it anywhere:
const client = new Ligantic({ apiKey: process.env.LIGANTIC_API_KEY! });The CLI's design goal is that the key never appears in shell history or in command arguments. It is never a flag.
On ligantic auth login, the key is read from piped stdin (echo $KEY | ligantic auth login) or a hidden prompt, then stored in the OS key store for a named profile (default: default; auth login --profile <name> stores for another, and auth use <name> switches the active one) when a key store is available:
When no key store is available (for example a headless Linux box with no Secret Service), the CLI warns that the key would be stored in plain text and asks for explicit consent before writing it into ~/.ligantic/config.json, which is created with 0600 (owner read/write only) permissions. In an interactive session it prompts; when non-interactive it fails safe and does not store unless --store-plaintext is passed. Declining leaves the key unstored — use LIGANTIC_API_KEY for future commands. This is the only case where the key ever touches a file.
ligantic auth login --no-store skips persistence entirely: the key is used for the current session only and is never written to the key store or a file.
The CLI resolves each setting with the same precedence, highest wins:
flag > env var > config file > built-in defaultSetting | Flag | Env var | Config file | Default |
|---|---|---|---|---|
Profile |
|
|
|
|
Space |
|
|
| none |
API key | — |
|
| OS key store |
Base URL | — |
|
|
|
The API key chain is specifically: LIGANTIC_API_KEY (env) > OS key store > config file (key-store fallback only).
A profile can carry its own base URL (profiles.<profile>.baseUrl), set with ligantic auth login --base-url <url> — flag-only, never prompted during login. This is how you point a profile at a different Ligantic server: each profile bundles its key and its server, and auth use / auth select switch both at once. The env var still wins over everything.
To use a profile for a single command without switching — for example in scripts, agents, or a sandbox where the config file is read-only — pass --profile <name> or set LIGANTIC_PROFILE. Neither writes the config file, so other shells keep their profile.
space use <id> and space select write the current profile's spaceId to the config file, so each profile remembers its own Space and switching profile switches Space too. This is the kubectl-style "current context": resource commands default to it unless you override with --space or LIGANTIC_SPACE_ID. It is not a secret — a Space ID is not sensitive — so it lives in the plain config file alongside the base URL.
0600 config file keeps the CLI usable on headless systems without a key store, while limiting the key to the owning user. Because it is plaintext, the CLI only writes it after an explicit warning and consent — and --no-store lets you opt out entirely.