Auth
auth
¶
Authenticates AI coding agents via OAuth or API key.
Two public entry points:
authenticate(project_id, provider, *, mounts_dir, image)— dispatches based on the provider'smodesfield: prompts for an API key (no container) or launches an auth container with the vendor CLI.store_api_key(provider, api_key)— stores an API key directly in the credential DB (non-interactive fast path for CI).
AUTH_PROVIDERS is a registry dict populated from the YAML roster at
package load time; authenticate looks up the provider by name and
delegates to the matching flow.
AUTH_PROVIDERS = {}
module-attribute
¶
All known auth providers (agents + tools), keyed by name. Loaded from resources/agents/*.yaml.
AuthProvider(name, label, host_dir_name, container_mount, command, banner_hint, extra_run_args=tuple(), modes=('api_key',), api_key_hint='', post_capture_state=dict())
dataclass
¶
Describes how to authenticate one tool/agent.
name
instance-attribute
¶
Short key used in CLI and TUI dispatch (e.g. "codex").
label
instance-attribute
¶
Human-readable display name (e.g. "Codex").
host_dir_name
instance-attribute
¶
Single-segment directory name under mounts_dir() (e.g. "_codex-config").
container_mount
instance-attribute
¶
Mount point inside the container (e.g. "/home/dev/.codex").
command
instance-attribute
¶
Command to execute inside the container (OAuth mode only).
banner_hint
instance-attribute
¶
Provider-specific help text shown before the container runs.
extra_run_args = field(default_factory=tuple)
class-attribute
instance-attribute
¶
Additional podman run arguments (e.g. port forwarding).
modes = ('api_key',)
class-attribute
instance-attribute
¶
Supported auth modes: "oauth" (container), "api_key" (fast path).
api_key_hint = ''
class-attribute
instance-attribute
¶
Hint shown when prompting for an API key (URL to get one).
post_capture_state = field(default_factory=dict)
class-attribute
instance-attribute
¶
JSON state files to write after credential capture.
Maps filename → key-value dict to merge into a JSON file in the auth
mount directory. Example: {".claude.json": {"hasCompletedOnboarding": true}}
marks Claude Code onboarding as complete so the first-run wizard is skipped.
supports_oauth
property
¶
Whether this provider supports OAuth (container-based) auth.
supports_api_key
property
¶
Whether this provider supports direct API key entry.
__post_init__()
¶
Validate fields that become filesystem paths.
Source code in src/terok_executor/credentials/auth.py
AuthKeyConfig(label, key_url, env_var, config_path, printf_template, tool_name)
dataclass
¶
Describes how to prompt for and store an API key.
label
instance-attribute
¶
Human name shown in the prompt (e.g. "Claude").
key_url
instance-attribute
¶
URL where the user can obtain the key.
env_var
instance-attribute
¶
Name shown in the read -p prompt (e.g. "ANTHROPIC_API_KEY").
config_path
instance-attribute
¶
Destination inside the container (e.g. "~/.claude/config.json").
printf_template
instance-attribute
¶
printf format string (e.g. '{"api_key": "%s"}').
tool_name
instance-attribute
¶
Name shown in the success message (e.g. "claude").
Authenticator(provider)
dataclass
¶
Vendor-credential acquisition for a single agent.
Wraps the authenticate flow behind a stable class so callers
that orchestrate a multi-step setup (terok project init, the
standalone terok-executor auth command, the TUI auth flow)
talk to one named surface bound to self.provider.
The discovery counterparts
(list_authenticated_agents,
scan_leaked_credentials)
stay as module-level fns in their owning submodules — folding them
in here would create a tach cycle through terok_executor.acp
and terok_executor.credentials.vault_commands, which already
depend on this module transitively.
provider
instance-attribute
¶
Auth provider name (e.g. "claude").
run(project_id, *, mounts_dir, image=None, expose_token=False, oauth_enabled=True, credential_set='default')
¶
Run the auth flow for self.provider; see module-level docs.
Mirrors the parameters of the underlying authenticate free
function — instance-bound self.provider replaces the old
positional provider arg.
Source code in src/terok_executor/credentials/auth.py
prepare_oauth(project_id, *, mounts_dir, image, expose_token=False, credential_set='default')
¶
Build an AuthSession without running it.
Frontends that own their own UI loop (e.g. the terok Textual TUI,
which wants to dispatch the OAuth container into a new terminal
tab or via tmux instead of inline) build the session here, run
session.argv however they like, then call session.capture()
on success. The CLI's blocking authenticate path is just
another such caller — see _run_auth_container.
Source code in src/terok_executor/credentials/auth.py
AuthSession(provider, project_id, container_name, argv, banner, auth_dir, mounts_dir, credential_set='default', expose_token=False, _tmpdir=None)
dataclass
¶
A prepared-but-not-run OAuth auth container session.
Built by Authenticator.prepare_oauth
(or the module-level prepare_oauth_session
helper). Hold-don't-call: the caller is responsible for running
argv (synchronously, in a new terminal tab, suspended TUI, etc.)
and calling capture() afterwards. Use as a context manager so
the temp dir and any dangling container are cleaned up on exit.
provider
instance-attribute
¶
Provider descriptor (label, banner hint, mount points).
project_id
instance-attribute
¶
Project scope for the banner; None for host-wide auth.
container_name
instance-attribute
¶
Podman container name (used for cleanup and -it log clarity).
argv
instance-attribute
¶
The podman run … command line — run this however you like.
banner
instance-attribute
¶
Banner text to display before launching argv.
auth_dir
instance-attribute
¶
Temp dir bind-mounted as the container's auth config target.
Lives until cleanup() (or __exit__). Credential extraction
in capture() reads from here, so don't remove it manually.
mounts_dir
instance-attribute
¶
Base directory for the shared post-capture mount (OAuth providers only).
credential_set = 'default'
class-attribute
instance-attribute
¶
Which credential set in the vault DB receives the captured token.
expose_token = False
class-attribute
instance-attribute
¶
When True, real credential files are copied into the shared mount (tier 3).
title
property
¶
Short human-readable title ("Authenticating Claude (host-wide)").
capture()
¶
Extract credentials from auth_dir, store them in the vault DB.
Call after argv exits successfully. Safe to call multiple
times (the underlying extractor is idempotent on a stable
credential file).
Source code in src/terok_executor/credentials/auth.py
cleanup()
¶
Release the temp dir and force-remove any lingering container.
Idempotent. __exit__ calls this automatically.
Source code in src/terok_executor/credentials/auth.py
__enter__()
¶
authenticate(project_id, provider, *, mounts_dir, image=None, expose_token=False, oauth_enabled=True, credential_set='default')
¶
Run the auth flow for provider, optionally scoped to a project.
Dispatches based on the effective mode set — what the provider
declares in the roster (modes:) intersected with what the
caller has actually permitted via oauth_enabled:
- api_key only (or OAuth disabled by gate): prompt for key, store directly
- oauth only: launch container with vendor CLI
- both: ask the user to choose, then dispatch accordingly
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
project_id
|
str | None
|
Project identifier used for container naming and the
banner line. Pass |
required |
provider
|
str
|
Auth provider name (e.g. |
required |
mounts_dir
|
Path
|
Base directory for shared config bind-mounts. |
required |
image
|
str | Callable[[], str] | None
|
Container image for the OAuth container. Either a tag
string (eager) or a zero-arg callable returning the tag
(lazy — invoked only when the user actually chooses the
OAuth path). |
None
|
expose_token
|
bool
|
When True, copy the real credential files into
the shared mount instead of writing a phantom marker. Used
by tier 3 ( |
False
|
oauth_enabled
|
bool
|
External gate for the OAuth path. |
True
|
credential_set
|
str
|
Storage namespace in the vault DB. Defaults to
|
'default'
|
Raises SystemExit if the provider name is unknown or no usable
auth mode remains after gating.
Source code in src/terok_executor/credentials/auth.py
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 | |
store_api_key(provider, api_key, credential_set='default')
¶
Store an API key directly in the credential DB (no container needed).
This is the non-interactive fast path for automated workflows and CI.
The key is stored as {"type": "api_key", "key": "<value>"}.
Source code in src/terok_executor/credentials/auth.py
prepare_oauth_session(provider, project_id, *, mounts_dir, image, expose_token=False, credential_set='default')
¶
Build an AuthSession without running it.
Creates a fresh temp dir, computes the podman run argv, and
cleans up any leftover container of the same name (so re-auth
after a previous abort isn't blocked). The caller drives execution
and credential capture; see AuthSession.
The temp dir uses a clean slate so the vendor auth flow re-runs end to end — no stale config, no cached sessions.
Source code in src/terok_executor/credentials/auth.py
api_key_command(cfg)
¶
Build a bash command that prompts for an API key and writes it to a config file.