Use apus onboard --non-interactive to script setup. It requires --accept-risk: non-interactive setup can write credentials and daemon config without a confirmation prompt, so the flag is the explicit risk acknowledgement.

Each command can install a managed Gateway with --install-daemon, require an already-running compatible Gateway by omitting daemon flags, explicitly leave the Gateway stopped with --skip-daemon, or use --skip-health for config-only setup. The explicit skip still checks for an existing Gateway and reports whether one is reachable, but an absent listener is informational rather than a setup failure.

--json does not imply non-interactive mode. Pass --non-interactive --accept-risk explicitly for scripts.

Review required plugins

Bundled plugins and verified plugins from Apus's official catalog do not require capability consent during setup. This includes the official Codex runtime installed for OpenAI setup.

Non-interactive onboarding cannot accept new third-party plugin capabilities. --accept-risk acknowledges onboarding risk only; it does not grant plugin consent. Before automating a setup that needs a third-party provider, runtime, or channel plugin, review its source and declared capabilities, then preinstall it with explicit consent:

apus plugins install <plugin-spec> --accept-capabilities

If onboarding reports a required plugin capability review, review and install the named plugin and rerun the same command. For an already-installed plugin that needs approval to enable it, use apus plugins enable <plugin-id> --accept-capabilities.

Consent applies to the reviewed plugin operation, not every subsequent install. See Capability consent for artifact review, enablement, and update rules.

Baseline non-interactive example

apus onboard --non-interactive --accept-risk \
  --mode local \
  --auth-choice apiKey \
  --anthropic-api-key "$ANTHROPIC_API_KEY" \
  --secret-input-mode plaintext \
  --gateway-bind loopback \
  --install-daemon \
  --daemon-runtime node \
  --skip-bootstrap \
  --skip-skills

Add --json for a machine-readable summary.

apus onboard --non-interactive --accept-risk --skip-health \
  --mode local \
  --auth-choice openai-api-key \
  --secret-input-mode ref

Provider-specific examples

Anthropic API key example
```bash
apus onboard --non-interactive --accept-risk --skip-health \
  --mode local \
  --auth-choice apiKey \
  --anthropic-api-key "$ANTHROPIC_API_KEY" \
  --gateway-bind loopback
```
Cloudflare AI Gateway example
```bash
apus onboard --non-interactive --accept-risk --skip-health \
  --mode local \
  --auth-choice cloudflare-ai-gateway-api-key \
  --cloudflare-ai-gateway-account-id "your-account-id" \
  --cloudflare-ai-gateway-gateway-id "your-gateway-id" \
  --cloudflare-ai-gateway-api-key "$CLOUDFLARE_AI_GATEWAY_API_KEY" \
  --gateway-bind loopback
```
Gemini example
```bash
apus onboard --non-interactive --accept-risk --skip-health \
  --mode local \
  --auth-choice gemini-api-key \
  --gemini-api-key "$GEMINI_API_KEY" \
  --gateway-bind loopback
```
Mistral example
```bash
apus onboard --non-interactive --accept-risk --skip-health \
  --mode local \
  --auth-choice mistral-api-key \
  --mistral-api-key "$MISTRAL_API_KEY" \
  --gateway-bind loopback
```
Moonshot example
```bash
apus onboard --non-interactive --accept-risk --skip-health \
  --mode local \
  --auth-choice moonshot-api-key \
  --moonshot-api-key "$MOONSHOT_API_KEY" \
  --gateway-bind loopback
```
Ollama example
```bash
apus onboard --non-interactive --accept-risk --skip-health \
  --mode local \
  --auth-choice ollama \
  --custom-model-id "qwen3.5:27b" \
  --gateway-bind loopback
```
OpenCode example
```bash
apus onboard --non-interactive --accept-risk --skip-health \
  --mode local \
  --auth-choice opencode-zen \
  --opencode-zen-api-key "$OPENCODE_API_KEY" \
  --gateway-bind loopback
```
Swap to `--auth-choice opencode-go --opencode-go-api-key "$OPENCODE_API_KEY"` for the Go catalog.
Synthetic example
```bash
apus onboard --non-interactive --accept-risk --skip-health \
  --mode local \
  --auth-choice synthetic-api-key \
  --synthetic-api-key "$SYNTHETIC_API_KEY" \
  --gateway-bind loopback
```
Vercel AI Gateway example
```bash
apus onboard --non-interactive --accept-risk --skip-health \
  --mode local \
  --auth-choice ai-gateway-api-key \
  --ai-gateway-api-key "$AI_GATEWAY_API_KEY" \
  --gateway-bind loopback
```
Z.AI example
```bash
apus onboard --non-interactive --accept-risk --skip-health \
  --mode local \
  --auth-choice zai-api-key \
  --zai-api-key "$ZAI_API_KEY" \
  --gateway-bind loopback
```
Custom provider example
```bash
apus onboard --non-interactive --accept-risk --skip-health \
  --mode local \
  --auth-choice custom-api-key \
  --custom-base-url "https://llm.example.com/v1" \
  --custom-model-id "foo-large" \
  --custom-api-key "$CUSTOM_API_KEY" \
  --custom-provider-id "my-custom" \
  --custom-compatibility anthropic \
  --custom-image-input \
  --gateway-bind loopback
```

`--custom-api-key` is optional; some endpoints do not require auth. If omitted, onboarding checks `CUSTOM_API_KEY` in env. `--custom-provider-id` is optional and auto-derived from the base URL when omitted. `--custom-compatibility` defaults to `openai` (other values: `openai-responses`, `anthropic`).

Apus infers image-input support from known vision model-id patterns (`gpt-4o`, `claude-3/4`, `gemini`, `-vl`/`vision` suffixes, and similar). Add `--custom-image-input` to force it on for an unrecognized vision model, or `--custom-text-input` to force text-only.

Ref-mode variant, storing `apiKey` as `{ source: "env", provider: "default", id: "CUSTOM_API_KEY" }`:

```bash
export CUSTOM_API_KEY="your-key"
apus onboard --non-interactive --accept-risk --skip-health \
  --mode local \
  --auth-choice custom-api-key \
  --custom-base-url "https://llm.example.com/v1" \
  --custom-model-id "foo-large" \
  --secret-input-mode ref \
  --custom-provider-id "my-custom" \
  --custom-compatibility anthropic \
  --custom-image-input \
  --gateway-bind loopback
```

Anthropic setup-token auth remains supported, but Apus prefers Claude CLI reuse when a local Claude CLI login is available. For production, prefer an Anthropic API key.

Add another agent

apus agents add <name> creates a separate agent with its own workspace, sessions, and auth profiles. Running it without --workspace (and no other flags) launches the interactive wizard; passing any of --workspace, --model, --agent-dir, --bind, or --non-interactive runs it non-interactively and then requires --workspace.

apus agents add work \
  --workspace ~/.apus/workspace-work \
  --model openai/gpt-6-astra \
  --bind whatsapp:biz \
  --non-interactive \
  --json

Config keys it writes (agents.entries.* entry for the new agent id):

Notes:

Related docs