Skip to content

Repository files navigation

Atem

A terminal that connects builders, Agora platform, and AI agents. Manage Agora projects and tokens, route tasks between Astation and AI coding agents, generate diagrams, drive voice-powered coding workflows, and more -- all from a single CLI/TUI.

Install

npm install -g @agora-build/atem

Or via shell script:

curl -fsSL https://dl.agora.build/atem/install.sh | bash

Or download a binary from Releases.

Build from source

git clone git@github.com:Agora-Build/Atem.git
cd Atem
cargo build --release
# Binary at target/release/atem

Commands

atem                                    # Launch TUI
atem repl                               # Interactive REPL with AI command interpretation

Authentication

atem login                              # Log in with Agora Console (opens browser)
atem logout                             # Log out from SSO

Tokens

atem token rtc create                   # Generate RTC token (interactive)
atem token rtc create --channel test --rtc-user-id 0 --expire 3600
atem token rtc create --channel test --rtc-user-id alice --with-rtm   # RTC + RTM in one token (reuses rtc-user-id)
atem token rtc create --channel test --rtc-user-id 42 --with-rtm --rtm-user-id bob  # Separate RTM account
atem token rtc decode <token>           # Decode existing RTC token
atem token rtm create                   # Generate Signaling (RTM) token
atem token rtm create --rtm-user-id bob --expire 3600
atem token rtm decode <token>           # Decode existing Signaling (RTM) token

Projects

atem project list                       # List Agora projects
atem project list --show-certificates   # List with app certificates visible
atem project use <APP_ID>               # Set current project by App ID
atem project use <N>                    # Set current project by index (1-based)
atem project show                       # Show current project

AI Agents (WIP)

atem agent list                         # Scan and list detected AI agents
atem agent launch                       # Launch Claude Code as PTY agent
atem agent launch codex                 # Launch Codex as PTY agent
atem agent connect <WS_URL>             # Connect to ACP agent and show info
atem agent prompt <WS_URL> "text"       # Send prompt to ACP agent
atem agent probe <WS_URL>               # Probe URL for ACP support
atem agent visualize "topic"            # Generate visual HTML diagram via agent
atem agent visualize "topic" --url ws://localhost:8765  # Explicit agent URL
atem agent visualize "topic" --no-browser               # Skip opening browser

Vault (shared cross-agent context)

atem vault new --summary "auth refactor context"   # Create a vault, prints its id
atem vault list                                     # List vaults you can read
atem vault read --vault-id <id>                     # Current contents
atem vault read --vault-id <id> --history           # Every version (shown eN vM)
atem vault read --vault-id <id> --format plain      # Bare text (pipe into a prompt)
atem vault write --vault-id <id> --text "decided: JWT in cookie"   # Append an entry
atem vault write --vault-id <id> --entry-id 3 --text "..."         # Override entry e3
atem vault set-summary --vault-id <id> --text "..."  # Update the summary

Lets multiple atems (each driving an agent) share a versioned, append-only context store via the relay. Requires a relay-hosted vault server (/api/vault); see designs/vault.md.

Dev Servers

atem serv convo                         # Launch ConvoAI test page (HTTPS)
atem serv convo --config ~/convo.toml   # Use custom config file
atem serv convo --background            # Detached daemon — POSTs /join, registers, exits
atem serv attach <ID>                   # Open UI bound to a running convo daemon (talk to live agent)
atem serv attach 3                      # …or by index from `atem serv list`
atem serv rtc                           # Launch RTC test page (HTTPS)
atem serv rtc --channel test --port 8443
atem serv rtc --background              # Run as background daemon
atem serv diagrams                      # Host diagrams from SQLite (HTTP)
atem serv diagrams --port 9000
atem serv diagrams --background
atem serv webhooks                      # Receive Agora webhooks locally (auto-tunneled via ngrok)
atem serv webhooks --no-tunnel          # Local listener only — bring your own tunnel
atem serv webhooks --background         # Run as background daemon
atem serv list                          # List running background servers (#, ID, PID, STATUS)
atem serv kill <ID|#>                   # Kill a server (POSTs /leave for convo)
atem serv killall                       # Kill all background servers

# Fleet test loop — {appid} and {ts} are expanded by atem
for i in $(seq -f '%04g' 1 10); do
  atem serv convo --background --channel 'atem-convo-{appid}-{ts}-'$i
done

serv convo — ConvoAI voice agent: live transcription (RTM), preset selection, avatar (Akool, LiveAvatar, Anam), RTC Stats, API History, camera toggle, RTC encryption (key + salt forwarded to the agent), HIPAA mode (routes via /hipaa/api/...), audio dump.

--background re-execs as a detached daemon: parent POSTs /join, registers the agent in ~/.config/atem/servers/<channel>.json, and exits. The daemon polls Agora's GET /agents/{id} every 60s and writes the status (RUNNING/IDLE/STOPPED/…) back into the registry — atem serv list reads it without making any network calls. kill/killall SIGTERM the daemon, which catches the signal and POSTs /leave before exiting. The daemon's log file (<channel>.log) contains the /join URL and request body with secrets masked, useful for debugging encryption mismatches.

serv attach <id> — opens a foreground HTTPS UI bound to a running convo daemon's channel. The page hides Start/Stop because the daemon owns the agent; you Join to talk to the live agent. Encryption / HIPAA / geofence are read from the same convo.toml so the local SDK matches what the daemon used.

serv rtc — RTC test page: join/leave, publish/subscribe audio+video, token generation, RTM messaging, RTC encryption (8 modes; gcm2 modes auto-generate a copyable salt).

serv diagrams — SQLite-backed HTTP server for hosting AI-generated HTML diagrams.

serv webhooks — local receiver for Agora webhook events (ConvoAI: agent_joined, agent_left, agent_history, agent_error, agent_metrics, …; RTC NCS events). Validates Agora-Signature-V2 (HMAC-SHA256) when a secret is configured in webhooks.toml; accepts unsigned events with a banner warning otherwise. Live web console at http://127.0.0.1:9090/ shows incoming events; each event also prints a one-line summary to stdout. Default tunnel provider is ngrok (requires ngrok config add-authtoken once); set tunnel_provider = "cloudflared" for zero-auth quick tunnels. Use --no-tunnel if you're running cloudflared / ngrok separately for stable URLs across atem restarts. See configs/webhooks.example.toml for the full config schema.

Channel placeholders--channel accepts {appid} (first 12 chars of the active app id) and {ts} (unix epoch seconds at startup). Useful in for-loops: --channel 'atem-convo-{appid}-{ts}-001' produces atem-convo-2655d20a82fc-1777574763-001.

Configuration

atem config show                        # Show resolved config
atem config set astation_ws <URL>       # Set Astation WebSocket URL
atem config set astation_relay_url <URL> # Set Astation relay URL
atem config clear                       # Clear active project selection
atem config convo                       # Interactive wizard to configure ConvoAI agent
atem config convo --validate            # Validate ConvoAI config without modifying
atem config convo --config <PATH>       # Use a specific config file

The atem config convo wizard walks you through Channel & User → Agent → Preset (empty = skip) → Add Custom override? → Pipeline → Avatar. Preset and Custom stack: preset sets defaults, explicit blocks override per-field. Pipeline selects one of:

  • Cascaded (ASR + LLM + TTS): 10 ASR, 9 LLM, 12 TTS vendors
  • Multimodal LLM: OpenAI Realtime (gpt-realtime), Google Gemini Live, xAI Grok Realtime — single model handles voice in/out
  • Avatar: Akool, LiveAvatar, Anam

convo.toml is structured into two atem-managed top-level sections plus the Agora pass-through tables. The web UI pre-fills form fields from [atem]; --background reads them directly.

[atem]                       # atem's runtime control surface
channel       = "..."        # auto-generated when omitted
rtc_user_id   = "0"          # human's RTC uid
pipeline      = "cascaded"   # "cascaded" | "mllm" — picks which block goes to /join
hipaa         = false        # route via /hipaa/api/... (Agora support must enable)
geofence      = "GLOBAL"     # GLOBAL | NORTH_AMERICA | EUROPE | ASIA | JAPAN | INDIA
enable_avatar = false        # opt in to use [agent.avatar] this session

[atem.encryption]            # mode = 0 → off
mode = 8                     # 1..=8 (Agora's table); 8 = AES_256_GCM2 (recommended)
key  = "your-key-here"
salt = "Q4mTLy5h…="           # base64 32 bytes; required for gcm2 modes (7, 8)

[agent]                      # the AI agent
user_id           = "1001"
idle_timeout_secs = 120
preset            = "preset_a, preset_b"   # comma-separated; UI splits into checkboxes

[agent.llm]                  # cascaded providers (forwarded under properties.<svc>)
[agent.asr]
[agent.tts]
[agent.mllm]                 # OR a single multimodal model — replaces asr+llm+tts
[agent.avatar]

[advanced_features]          # pass-through (forwarded verbatim to Agora)
[vad]
[sal]
[parameters]

Both peers must use matching encryption/geofence or audio fails silently. enable_avatar is opt-in even when [agent.avatar] is configured — fleet --background launches won't burn avatar minutes by accident. atem config convo --validate reports any issue (unknown geofence, gcm2 mode without salt, missing [agent].user_id, etc.).

How It Works

Astation connections

Atem tries a configured direct endpoint first and then the identity relay after it has learned the target Astation identity. Direct and relay connections use the same device session, so one Atem can move between networks without pairing again. Successful authentication stores astation_relay_code automatically; manual configuration is only needed for an override or headless provisioning.

Atem location Endpoint First connection Internet required
Same Mac ws://127.0.0.1:8080/ws Transparent same-user proof No
Another LAN machine ws://<astation-ip>:8080/ws Approve pairing in Astation No
Remote network Public WSS identity relay Approve pairing in Astation Yes

All paths use device authentication v2. Astation sends a fresh challenge; Atem proves possession of the local bootstrap token or its saved device-session token with HMAC-SHA256. A session ID by itself is not accepted. Same-Mac operation continues when Wi-Fi is disabled, and LAN operation needs no relay once the IP is configured.

Direct LAN currently uses plaintext ws://. Authentication prevents a stolen session ID from being sufficient, but it does not stop traffic inspection or an active LAN attacker during initial pairing. Treat direct LAN as pre-production until WSS certificate pinning is implemented. The wire contract and test matrix are documented in designs/session-auth.md.

TUI Modes

Mode Description
Token Gen Generate Agora RTC/RTM tokens locally
Projects Browse and select Agora projects
Claude Chat Claude Code integration via PTY
Codex Chat Codex terminal integration via PTY

Diagram Generation

atem agent visualize "topic" sends a prompt to a running AI agent (via ACP), which generates a self-contained HTML diagram and saves it to ~/.agent/diagrams/. Atem detects the new file, hosts it via atem serv diagrams, and opens it in the browser. Use --url ws://host:port to target a specific agent.

Astation integration and voice-driven coding are in progress — see ROADMAP.md.

Configuration

Login

atem login          # Opens browser to log in with Agora Console

If the browser redirect doesn't complete within 5 seconds (e.g. remote server), atem will prompt you to paste the callback URL from the browser address bar.

Storage

Files in ~/.config/atem/:

File Contents Encryption
config.toml Non-sensitive settings (extra_hostnames, SSO/BFF overrides) None
convo.toml ConvoAI agent config (API keys, provider params) None (chmod 0600)
credentials.enc SSO tokens AES-256-GCM (machine-bound)
project_cache.enc Project list + active project selection AES-256-GCM (machine-bound)
sessions.json Per-Astation device session IDs and tokens Plaintext (chmod 0600)

Encrypted files are bound to the machine they were created on — copying them to another machine won't decrypt.

Config file

~/.config/atem/config.toml:

# astation_ws = "ws://127.0.0.1:8080/ws"
# astation_relay_url = "https://station.agora.build"
# astation_relay_code = "astation-..." # learned automatically after authentication
# bff_url = "https://agora-cli.agora.io"
# sso_url = "https://sso2.agora.io"

# Extra hostnames baked into the self-signed cert + shown as "Custom:" URLs
# extra_hostnames = ["genie.netbird.cloud", "dev.mytailnet.ts.net"]

Environment variable overrides

ATEM_BFF_URL=...   # Override BFF API base URL
ATEM_SSO_URL=...   # Override SSO base URL
ASTATION_WS=...            # Direct loopback, LAN, or VPN WebSocket endpoint
ASTATION_RELAY_URL=...     # Relay HTTP(S) base URL
ASTATION_RELAY_CODE=...    # Target Astation identity room
AGORA_APP_ID=...           # Override active project App ID
AGORA_APP_CERTIFICATE=...  # Override active project certificate

Development

cargo build                       # Debug build
cargo build --release             # Release build
cargo test                        # Run tests (500+ tests)
cargo check                       # Type-check
cargo fmt                         # Format
cargo clippy                      # Lint
./scripts/run-local-dev-tests.sh  # End-to-end CLI smoke test
./scripts/release.sh              # Patch-bump Cargo.toml + commit + tag
./scripts/release.sh 0.5.0        # Explicit version

Release

Releases are tag-driven — pushing vX.Y.Z triggers .github/workflows/release.yml, which builds the binaries and publishes @agora-build/atem to npm.

Use ./scripts/release.sh rather than git tag directly — the script keeps Cargo.toml in sync with the tag, so atem --version reports the right number.

Feature Flags

Flag Description
real_rtm Link against Agora RTM SDK (default: stub)
openssl-vendored Build OpenSSL from source (for cross-compilation)

Roadmap

See ROADMAP.md for upcoming features and where to help. Items labelled help wanted are open for contributors.

Related Projects

  • Astation -- macOS menubar hub that coordinates Chisel, Atem, and AI agents — talk to your coding agent from anywhere
  • Chisel -- Dev panel for visual annotation and UI editing by anyone, including AI agents
  • Vox -- AI latency evaluation platform

License

MIT

About

A terminal that connects builders, Agora platform, and AI agents.

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages