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"
# 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 20260325T114502Z-claude-ci --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”All inventory and status commands support --json:
aisw status --jsonaisw status --context --jsonaisw list --jsonaisw list claude --jsonaisw context list --jsonaisw backup list --jsonaisw doctor --jsonJSON output goes to stdout. Errors always go to stderr with a non-zero exit code.
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'
# List all stored Codex profile namesaisw list codex --json | jq -r '.profiles[].name'
# List all saved contextsaisw context list --json | jq -r '.contexts[].name'
# Find profiles with expired tokensaisw status --json | jq '.[] | select(.token_warning != null) | {tool, warning: .token_warning}'
# Get the most recent backup for a specific profileaisw backup list --json | jq '[.[] | select(.profile == "claude/work")] | sort_by(.created_at) | last'Output contract
Section titled “Output contract”| Output | Destination | Notes |
|---|---|---|
| Human-readable tables and status | stdout | Suppressed by --quiet |
| Errors | stderr + non-zero exit | Always present, never suppressed |
| 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 |
Exit code 0 means success. Any non-zero exit code means failure; the error message is on stderr.
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