CLI OAuth
Overview
The CLI OAuth feature lets agents use gh (GitHub CLI) and lark-cli directly from
sandbox sessions without manual authentication. Anna handles the OAuth device flow on
the host, stores a versioned token bundle in your personal vault, and injects a fresh
runtime token into each sandbox environment automatically.
Prerequisites
GitHub works out of the box. Anna uses the public GitHub CLI OAuth device-flow app, so users can connect their GitHub account without any admin-side plugin settings.
Feishu / Lark still requires an admin to configure an app ID, app secret, and
brand in the Lark CLI plugin settings before users can connect. The brand selects
both the OAuth provider and the injected LARKSUITE_CLI_BRAND value. The default
brand is feishu; choose lark for international Lark. Leave redirect_url
empty unless you need an override: Anna derives it from the current Admin UI origin,
such as http://localhost:25678/api/auth/profile/oauth/feishu/callback.
Connecting
Via the credentials tool (channel sessions)
Inside any Anna channel session, ask the agent to connect a provider. It will call the
credentials tool, which starts a device flow and returns a verification URL and user
code. Open the URL in a browser, enter the code, and authorize. The agent polls for
completion automatically and resumes your task once connected.
Via the admin panel (web UI)
- Open the Anna admin panel and navigate to your Credentials page.
- Find the OAuth CLI Credentials section.
- Click Connect next to the provider you want to link.
- Anna starts a device flow and displays a verification URL and user code.
- Open the URL in a browser, enter the code, and authorize.
- Anna polls for completion. Once authorized, the token bundle is saved to your vault.
You can disconnect at any time by clicking Disconnect next to the provider, or by
asking the agent to run credentials disconnect for the relevant provider.
Choosing Feishu or Lark for lark-cli
lark-cli uses the brand field in the Lark CLI plugin config as the single
selector:
brand: feishuuses the Feishu OAuth endpoints and injectsLARKSUITE_CLI_BRAND=feishu.brand: larkuses the international Lark OAuth endpoints and injectsLARKSUITE_CLI_BRAND=lark.
You do not need to duplicate that choice in $ANNA_HOME/plugins.yaml. The built-in
manifest resolves oauth_provider from the plugin config field:
oauth_provider_config_field: brand
oauth_provider_choices: [lark, feishu]
session_env:
- env_var: LARKSUITE_CLI_BRAND
source: oauth.brandOnly override tool/lark-cli in $ANNA_HOME/plugins.yaml if you need to change the
binary or session environment declarations themselves.
Using the CLIs
After connecting, raw gh and lark-cli commands work inside agent sandbox sessions
without any additional configuration. Anna injects the required auth env for each
session and prepends $ANNA_HOME/bin to PATH, so gh and lark-cli resolve
straight to Anna-managed binaries. For lark-cli, Anna injects
LARKSUITE_CLI_USER_ACCESS_TOKEN, LARKSUITE_CLI_APP_ID, and
LARKSUITE_CLI_BRAND, so no per-session config init is required.
Example (issued by the agent inside a bash tool call):
gh issue list --repo owner/repo
lark-cli message send --chat-id <id> --text "Hello"Known limitations
Feishu/Lark token expiry
Feishu and Lark user access tokens expire after approximately 2 hours. Anna
proactively refreshes them when a token is within 10 minutes of expiry. If a token
expires mid-session, re-authenticate using the oauth tool or the Credentials page;
Anna will automatically restart the sandbox with the new token on the next message.
Restart loses in-flight device flows
Pending device flows (started but not yet authorized) are held in memory. An Anna
process restart discards them. If Anna restarts while you are completing authorization
in a browser, you will need to start the flow again (via the credentials tool or the
Credentials page).
Security model
OAuth token bundles (GH_OAUTH, FEISHU_CLI_OAUTH, and LARK_CLI_OAUTH when the
lark-cli brand is lark) are stored encrypted at rest in your vault
using the same age-based encryption as other vault entries. They are treated as
host-only data: the raw JSON bundles are never forwarded into the sandbox process
environment. Only the derived runtime token (for example, GH_TOKEN for GitHub) is
injected, so sandbox processes never receive refresh credentials or OAuth app secrets.