Automation and Scripting
aisw is designed to be used safely in CI pipelines, shell scripts, and non-interactive environments.
Baseline flags
Section titled “Baseline flags”aisw --non-interactive --quiet <command>| Flag | Effect |
|---|---|
--non-interactive | Fail instead of prompting. Safe for CI - commands that require user input will exit non-zero with a clear error. |
--quiet | Suppress human-readable presentation output (tables, status lines). Does not suppress errors, JSON output, --emit-env, or shell-hook output. |
--yes | Skip confirmation prompts on commands that ask before proceeding (remove, restore, uninstall). |
Non-interactive patterns
Section titled “Non-interactive patterns”# Add an API key profile without any promptsaisw --non-interactive add claude ci --api-key "$ANTHROPIC_API_KEY"
# Or avoid passing the secret in argvprintf '%s' "$ANTHROPIC_API_KEY" | aisw --non-interactive add claude ci --api-key-stdin --json
# Add from an already-exported environment variableaisw --non-interactive add codex ci --from-env
# Remove a profile with no confirmationaisw --non-interactive remove codex ci --yes
# Restore a backup with no confirmationaisw --non-interactive backup restore 2026-03-25T11-45-02.123Z-0000 --yesInteractive OAuth flows (aisw add claude personal without flags) are not available in --non-interactive mode. Use --api-key or --from-env for CI.
Machine-readable output
Section titled “Machine-readable output”Read commands support --json, and core mutation commands now expose machine envelopes as well:
aisw version --jsonaisw capabilities --jsonaisw init --json --no-shell-hook --detect-liveaisw add claude work --api-key-stdin --jsonaisw use claude work --jsonaisw context create work --claude work-claude --codex work-codex --jsonaisw context use work --jsonaisw context rename work client-acme --jsonaisw context remove client-acme --yes --jsonaisw remove claude work --yes --jsonaisw rename claude work personal --jsonaisw backup restore 2026-03-25T11-45-02.123Z-0000 --yes --jsonaisw verify --jsonaisw repair --json --dry-runaisw workspace bind --default --context work --jsonaisw workspace unbind --default --jsonaisw workspace guard --mode strict --jsonaisw project-bindings list --jsonaisw status --jsonaisw status --context --jsonaisw list --jsonaisw list claude --jsonaisw context list --jsonaisw backup list --jsonaisw doctor --jsonWith --json, success and expected command failures are emitted as structured JSON on stdout. Human-oriented stdout/stderr output is suppressed. The process still exits non-zero on failure.
For OAuth-based add, use --progress-json to stream newline-delimited JSON progress events:
aisw add claude personal --progress-jsonExample event stream:
{"type":"started","seq":1,"command":"add","tool":"claude","profile":"personal"}{"type":"waiting_for_user","seq":3,"command":"add","tool":"claude","profile":"personal","phase":"waiting_for_user","safe_to_cancel":true,"message":"Complete login in the browser or terminal"}{"type":"result","seq":5,"command":"add","tool":"claude","profile":"personal","ok":true,"result":{"tool":"claude","profile":"personal","auth_method":"oauth","credential_backend":"file","active":false,"source":null,"warnings":[]}}Useful JSON patterns
Section titled “Useful JSON patterns”# Get the active Claude profile name from the plain status arrayaisw status --json | jq -r '.[] | select(.tool == "claude") | .active_profile'
# Get the derived active context nameaisw status --context --json | jq -r '.context.active'
# Check whether the live credentials match the active Claude profileaisw status --json | jq '.[] | select(.tool == "claude") | .active_profile_applied'
# Get a one-shot pass/warn/fail verification verdictaisw verify --json | jq -r '.summary.status'
# Preview safe local repairs and count remaining issuesaisw repair --json --dry-run | jq -r '.result.summary.issues_remaining'
# List all stored Codex profile names# `list --json` is grouped by tool binary name, so index the tool key first.# Antigravity is keyed as "agy".aisw list codex --json | jq -r '.codex.profiles[].name'
# List all saved contextsaisw context list --json | jq -r '.contexts[].name'
# Activate a saved context and read the refreshed active profile mapaisw context use work --json | jq '.result.active'
# Update the default workspace context and inspect the refreshed binding snapshotaisw workspace bind --default --context work --json | jq '.result.project_bindings.user_bindings'
# Remove the default workspace context and inspect the refreshed binding snapshotaisw workspace unbind --default --json | jq '.result.project_bindings.user_bindings'
# Persist strict workspace guard mode and confirm the saved modeaisw workspace guard --mode strict --json | jq -r '.result.guard_mode'
# List user workspace rules plus the current repo-local bindingaisw project-bindings list --json | jq '.result'
# Find tools whose live credentials no longer match the recorded active profileaisw status --json | jq '.[] | select(.active_profile_applied == false) | {tool, active_profile}'
# Find tools with missing credentials or overly broad permissionsaisw status --json | jq '.[] | select(.credentials_present == false or .permissions_ok == false) | .tool'
# Get the most recent backup for a specific profile# Backup ids sort lexicographically, newest last.aisw backup list --json | jq -r '[.[] | select(.tool == "claude" and .profile == "work")] | sort_by(.backup_id) | last | .backup_id'Output contract
Section titled “Output contract”| Output | Destination | Notes |
|---|---|---|
| Human-readable tables and status | stdout | Suppressed by --quiet |
| Errors in human mode | stderr + non-zero exit | Always present, never suppressed |
Errors in machine mode (--json, --progress-json) | stdout + non-zero exit | Structured JSON envelope |
| Prompts | stderr or tty | Only shown without --non-interactive and without --yes |
aisw use --emit-env / aisw context use --emit-env | stdout | Shell variable exports; not affected by --quiet |
aisw shell-hook | stdout | Shell hook code; not affected by --quiet |
JSON output (--json) | stdout | Not affected by --quiet |
Progress JSON (--progress-json) | stdout | One JSON object per line, intended for GUI/OAuth flows |
Exit codes
Section titled “Exit codes”Exit code 0 means success. Any non-zero exit code means failure; the error message is on stderr in human mode, or in the JSON envelope on stdout in machine mode.
| Code | Meaning |
|---|---|
0 | Success |
2 | Profile not found - lets a script tell a wrong name from a real failure |
1 | Every other failure |
The JSON failure envelope carries the same information in a stable shape:
{ "ok": false, "error": { "kind": "profile_not_found", "message": "profile 'ghost' not found for claude.\n Run 'aisw list claude' to see available profiles.", "exit_code": 2, "remediation": { "kind": "run_command", "command": "aisw list claude", "safe": true } }}Branch on error.kind, not on the message text - kind is stable, the message is not. remediation is present only when a suggested next command exists; safe: true means it is read-only and can be run automatically.
aisw doctor and aisw verify exit non-zero when a check fails, so they work directly as CI gates.
aisw use --all
Section titled “aisw use --all”--all switches every tool that has a profile with the given name:
- A tool with no such profile is skipped, and the command still succeeds.
- A tool that has the profile but fails to switch is reported, and the command exits non-zero with the standard failure envelope.
So a zero exit means every tool that could switch did switch. If you need to know which tools were affected, read result.affected_tools from --json on success.
Applying profiles without the shell hook
Section titled “Applying profiles without the shell hook”If the shell hook is not installed, aisw use still writes live credential files and updates the active profile in config. For commands that need the env vars emitted by aisw use:
# Apply profile and capture env exports into the current shelleval "$(aisw use codex work --emit-env)"
# Apply a saved cross-tool context into the current shelleval "$(aisw context use acme --emit-env)"
# Or in a subshell(eval "$(aisw use claude work --emit-env)"; claude ...)--emit-env prints export VAR=value or unset VAR lines for any environment variables the activation sets (e.g. CLAUDE_CONFIG_DIR, CODEX_HOME, GEMINI_API_KEY).
Concurrency
Section titled “Concurrency”Commands that write ~/.aisw/config.json take an exclusive file lock. If two aisw commands run concurrently, the second will wait briefly then fail with a lock error. This prevents partial writes in parallel CI matrix jobs. Design your CI steps so profile setup runs before parallel job steps that invoke the tools.
Common CI patterns
Section titled “Common CI patterns”Set up a named profile in CI
Section titled “Set up a named profile in CI”# GitHub Actions or similar- name: Configure Codex profile env: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} run: | aisw --non-interactive add codex ci --from-env aisw use codex ciSwitch profile before a tool invocation
Section titled “Switch profile before a tool invocation”aisw --non-interactive use claude workclaude --print "summarize this file" < input.txtVerify active profile in a health check
Section titled “Verify active profile in a health check”active=$(aisw status --json | jq -r '.[] | select(.tool == "claude") | .active_profile')if [ "$active" != "ci" ]; then echo "Expected profile 'ci', got '${active}'" >&2 exit 1fiClean up after CI
Section titled “Clean up after CI”aisw --non-interactive remove codex ci --yesRelated
Section titled “Related”- Commands - full flag reference
- Shell integration - hook installation and env var behavior
- Quickstart - interactive usage reference