Credentials & Connecting Providers
How you give Axtary access to GitHub / Slack / Linear without pasting long-lived tokens around — and where those secrets live.
The governing rule: the credential broker is local. Provider secrets stay on your machine and never reach Axtary's hosted control plane (see Core concepts → the two planes). There are three supported ways to supply a credential, in order of preference.
1. axtary connect — browser OAuth, token stored locally (recommended)
Instead of hand-copying a bot token, run a browser OAuth flow. The token is written to the local credential broker (OS keychain when available, else a 0600 file at ~/.axtary/credentials.json) and is never printed.
axtary connect linear # opens the browser, you click "Allow" (http loopback)
axtary connections # list connected providers (metadata only, never secrets)
axtary disconnect linear # remove a stored credential
This is the gh auth login model: a loopback redirect to 127.0.0.1 captures the authorization code locally and exchanges it locally. Axtary never sees your OAuth client secret or the resulting token — both stay on your machine.
One-time setup: bring your own OAuth app
Because Axtary is not a credential custodian, you register your own OAuth app and provide its client id/secret via local env (read by name, never stored by Axtary):
| Provider | Register | Redirect URI | Env |
|---|---|---|---|
| Linear ✅ loopback | linear.app → Settings → API → OAuth application (scopes read,write) | http://127.0.0.1:7878/callback | AXTARY_LINEAR_CLIENT_ID, AXTARY_LINEAR_CLIENT_SECRET |
| Slack ⚠️ needs HTTPS | api.slack.com/apps → OAuth & Permissions (scope chat:write) | https://<tunnel>/callback (Slack rejects http) | AXTARY_SLACK_CLIENT_ID, AXTARY_SLACK_CLIENT_SECRET |
# Linear — works with a plain http loopback:
export AXTARY_LINEAR_CLIENT_ID=...
export AXTARY_LINEAR_CLIENT_SECRET=...
axtary connect linear
Slack requires an HTTPS redirect URL — it rejects
http://127.0.0.1/http://localhost. The local loopback alone can't satisfy this, soaxtary connect slackfails fast unless you pass an HTTPS redirect (--redirect-uri https://<tunnel>/callback) that a tunnel (e.g. ngrok) forwards to your local port. For most teams it's simpler to keep Slack on the bot token in env (below) until the hosted OAuth broker ships (roadmap), which gives Slack a proper HTTPS callback with no tunnel.
# Slack via a tunnel: register the https URL in your Slack app, then:
axtary connect slack --redirect-uri https://your-subdomain.ngrok.io/callback --redirect-port 7878
Flags: --client-id <id> / --client-id-env NAME / --client-secret-env NAME override the defaults; --redirect-port is the local listen port; --redirect-uri is the URL advertised to the provider (defaults to the http loopback; use an HTTPS tunnel URL for Slack); --json for scripting.
Once connected, doctor, smoke, proxy, and run workflow all resolve the token from the broker automatically — a connected provider reads as ready even with no env var set. A broker token takes precedence over the env var; an expired OAuth credential falls back to the env var.
GitHub uses a different path: the GitHub App install flow with short-lived installation tokens (github.mode: app). There is no axtary connect github.
2. Bring your own secret manager (env-name indirection)
Every connector references its credential by env-var name, never by value (tokenEnv, privateKeyEnv, appIdEnv, accessKeyIdEnv, …). That env var can be populated by whatever secret manager you already run — Axtary reads the name and lets your tooling inject the value:
# 1Password
op run --env-file=.env.axtary -- axtary run workflow github-pr-review --real ...
# Doppler
doppler run -- axtary proxy --config axtary.yml
# Vault (agent/template renders the env), AWS Secrets Manager, SOPS, etc.
Nothing about the secret is committed, logged, or stored by Axtary. This is the zero-extra-setup path for teams that already centralize secrets, and it composes with the broker (broker first, then env).
3. Manual token (local bootstrap)
The simplest path still works: set the connector's tokenEnv to a token you paste into your shell/secret store. Fine for a quick local trial; prefer (1) or (2) for anything ongoing because long-lived pasted tokens are the weakest option.
Where secrets live (and don't)
- Broker file:
~/.axtary/credentials.json,0600. Holds connection metadata (provider, scopes, expiry, source) plus — only when the keychain is unavailable — the token. On macOS the token is kept in the login keychain and the file holds metadata only. axtary connectionsreads metadata only, so it can never print a secret.- Tokens are never written to the ledger, hosted sync payloads, dashboard, or logs.
- The hosted dashboard cannot see local credentials by design; its connectors page documents
axtary connectrather than showing connection state.
Roadmap (Coming Soon)
- AWS/GCP keyless via Workload Identity Federation / OIDC — no static keys at all; exchange a short-lived OIDC token for a short-lived provider token. The gold standard for cloud, implemented when a cloud design partner needs guarded cloud actions.
- Hosted OAuth broker (pass-through) — an optional mode where the hosted plane holds only the OAuth client secret, performs the code exchange, and hands the token straight to the local plane without persisting it. Gives Slack a clickless HTTPS callback with no tunnel. Built when a partner needs fully clickless hosted onboarding.
- Device authorization grant (RFC 8628) for headless/CI where no browser is available on the same machine.
- OAuth token refresh for providers that issue short-lived access tokens with refresh tokens.
Next: Integrate your agent to route Claude Code or an MCP client through Axtary.