> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sente.run/llms.txt
> Use this file to discover all available pages before exploring further.

# CLI

> The sente command-line tool — identities, inbox, verification codes, register/connect, sessions, and webhooks from the terminal.

`@sente-labs/cli` installs the `sente` binary. It targets the same REST API as the SDKs
(`https://api.sente.run/v1`) and is built for terminals, scripts, and agent shells. Requires
Node.js 18+.

```bash theme={null}
npm install -g @sente-labs/cli
```

## Sign in

```bash theme={null}
sente login     # opens the browser (Auth0), mints and stores an API key
sente whoami    # show the logged-in account + organization
sente token     # print the stored key (for piping into .env)
```

`sente login` stores the key in `~/.sente/credentials` (mode 0600). The key authenticates
your whole organization — don't paste it into chats or commit it. To hand it to your app
without echoing it:

```bash theme={null}
echo "SENTE_API_TOKEN=$(sente token)" >> .env
```

For CI or non-interactive use, set env vars instead of logging in:

```bash theme={null}
export SENTE_API_TOKEN=sk_sente_...              # or: sente login --token <key>
export SENTE_GATEWAY_URL=https://api.sente.run   # optional override
```

`sente login --non-interactive` fails rather than opening a browser. Add `--json` to any
command for machine-readable output.

## Identities

```bash theme={null}
sente identity create --name "Support Bot" --local-part support-bot
# -> support-bot@sente.run
sente identity list
sente identity show <ref>
```

`identity create` options: `--name`, `--description`, `--local-part` (default: random),
`--on-conflict error|suffix` (default `error` — fail if the address is taken; `suffix`
appends a random suffix). Everywhere below, `<ref>` is an identity id, email, or
local-part.

## Read the inbox and wait for codes

```bash theme={null}
sente inbox --identity support-bot                  # recent messages (--since, --direction, --limit)
sente wait --identity support-bot --timeout 60      # block until the next message
sente listen --identity support-bot                 # stream messages as they arrive (Ctrl-C to stop)
```

Verification emails: `--otp` / `--magic-link` block for the verification message and print
**just** the extracted code or link, so the output is pipeable:

```bash theme={null}
CODE=$(sente wait --identity support-bot --otp --timeout 120)
LINK=$(sente wait --identity support-bot --magic-link --timeout 120)
```

`wait` accepts `--since <ts>` (ISO timestamp; stamp it before triggering the action for
back-to-back flows — see [Receive verification codes](/guides/receive-verification-codes))
and `--timeout <s>` (default 25; the CLI loops the server's 60-second long-poll, so any
timeout works). `--otp` and `--magic-link` are mutually exclusive.

`listen` can react to each message instead of printing it:

```bash theme={null}
sente listen --identity support-bot --exec './handle-message.sh'          # message JSON on stdin
sente listen --identity support-bot --forward http://localhost:3000/sente # local webhook testing
```

`--forward` POSTs each inbound message in the exact webhook envelope (with `x-sente-secret`
taken from `SENTE_WEBHOOK_SECRET`, if set) — useful for developing a webhook handler with
no public URL.

## Send and reply

```bash theme={null}
sente send --identity support-bot --to user@example.com \
  --subject "Hello" --text "It works."

# Reply in-thread to an inbound message:
sente send --identity support-bot --to user@example.com \
  --subject "Re: Hello" --text "Following up." --reply-to <messageId>
```

`--text` and/or `--html` is required.

## Register at a third-party app

`sente register` drives a browser through signup at the app under the identity's email and
completes email verification from the identity's own inbox. It blocks until the run
finishes, printing status lines as it goes.

```bash theme={null}
sente register https://app.example.com/signup --identity support-bot
sente registrations --identity support-bot     # list accounts + latest run status
sente relogin <registrationId>                 # re-authenticate later
sente credentials <registrationId>             # print the vaulted username/password/origin
```

Options: `--username` / `--password` (defaults are generated server-side),
`--confirm-before-submit`, `--autonomous`, `--no-wait` (return the run id immediately).

<Warning>
  Register only at apps whose terms permit it. In an interactive terminal, `register` asks
  whether the agent should submit the form itself or pause for you; `--confirm-before-submit`
  forces the pause: the agent fills the form, then the run goes `blocked` with a live-view
  URL — you click the final submit yourself (and accept the app's terms), then
  `sente run resume <runId>` continues. See [Acceptable use](/trust/acceptable-use).
</Warning>

CAPTCHAs and SMS verification are not automated either: the run goes `blocked` and a human
finishes the step in the interactive live view, then resumes. See
[Runs and human takeover](/concepts/runs-and-human-takeover).

Inspect and control runs:

```bash theme={null}
sente run <runId>            # status, error code, live-view URL (alias for `sente run show`)
sente run resume <runId>     # resume a blocked run after human takeover
sente run abort <runId>      # abort a non-terminal run
```

## Get notified when a run needs you

`sente watch` polls for `blocked` runs and desktop-notifies (macOS Notification Center;
terminal bell elsewhere) with the live-view URL and the resume command — no webhook server
needed:

```bash theme={null}
sente watch                       # all identities
sente watch --identity <ref>      # one identity
sente watch --interval 10         # poll every 10s (default 5)
```

Prefer push? Subscribe a webhook to `run.blocked` (see below).

## Connect an account you already own

`sente connect` is delegated access to an existing account: you supply the credentials,
Sente logs in, vaults them **write-only**, and keeps the account re-loginable. See the
[Connect guide](/guides/connect).

```bash theme={null}
sente connect https://app.example.com/login --identity support-bot \
  --username you@yourco.com --password '<password>' \
  --totp-seed '<base32-or-otpauth-uri>'    # optional

sente connections                          # list connected accounts + latest run
sente connection revoke <connectionId>     # stop using it; vaulted creds kept (reconnect re-enables)
sente connection delete <connectionId>     # revoke AND purge the stored credentials
```

`--totp-seed` vaults the authenticator secret (the base32 string behind a QR code's
"can't scan?" link, or a full `otpauth://` URI) so re-login clears TOTP 2FA without a
human — the server computes the 30-second code; the seed never reaches any model.

<Note>
  Limits: SSO-only accounts (Google/Okta sign-in, passkeys) cannot be connected. On connected
  accounts `sente credentials` returns 403 `CREDENTIALS_WRITE_ONLY` — credentials are
  write-only. Email or SMS code MFA blocks the run with `MFA_REQUIRED` — enter the code in
  the live view, then `sente run resume <runId>` — unless the account uses TOTP (vaulted
  seed) or its notification email was repointed to the Sente identity.
</Note>

`connect` supports `--no-wait` like `register`.

## Sessions

Open a remote browser already logged into an account. The CDP URL prints alone on stdout
(pipeable); everything else goes to stderr. If the login went stale, the CLI re-logs-in
first (vaulted credentials + a fresh code from the identity's inbox) before handing you
the session.

```bash theme={null}
CDP_URL=$(sente session open <registrationId>)   # or just: sente session <registrationId>
# ... drive it with connectOverCDP / puppeteer.connect ...
sente session close <registrationId>             # idempotent
```

`--no-verify` skips the freshness check (raw). One live session per identity; open
sessions count against your plan's browser-minute allowance — close when done.

Export the logged-in browser state (cookies + localStorage) as a Playwright
`storageState` JSON to load into your own browser stack (written mode 0600 — it's a bearer
credential, store it like a secret):

```bash theme={null}
sente session export <registrationId> [outPath]
# default outPath: ./<registrationId>-storageState.json
# load with: browser.newContext({ storageState })
```

Works for created and connected accounts. More in the [Sessions guide](/guides/sessions).

## Webhooks

```bash theme={null}
sente webhook register --url https://my-app.com/hooks/sente --identity support-bot
sente webhook register --url https://my-app.com/hooks/sente --events run.blocked
sente webhook list
sente webhook delete <id>
```

`--events` is a comma-separated list (default `message.received`); omit `--identity` for
org-wide. The register output includes your organization's signing secret (`webhook list`
never shows it) — verify the `x-sente-secret` header on every delivery. `run.blocked` payloads carry the block `code`,
`liveViewUrl`, a dashboard `actionUrl`, and `holdExpiresAt`; `run.completed` and
`run.failed` fire on terminal runs. Payloads and verification code in the
[Webhooks guide](/guides/webhooks).

## Command reference

| Command                                              | What it does                                                                      |
| ---------------------------------------------------- | --------------------------------------------------------------------------------- |
| `sente login`                                        | Browser sign-in; mints and stores an API key (`--token`, `--non-interactive`)     |
| `sente whoami`                                       | Show the logged-in account + organization                                         |
| `sente token`                                        | Print the stored API key                                                          |
| `sente identity create\|list\|show`                  | Manage email identities                                                           |
| `sente inbox --identity <ref>`                       | List recent messages                                                              |
| `sente wait --identity <ref>`                        | Block until the next message; `--otp` / `--magic-link` print just the code / link |
| `sente listen --identity <ref>`                      | Stream messages; `--exec` / `--forward` to react                                  |
| `sente send --identity <ref>`                        | Send email (`--reply-to` threads replies)                                         |
| `sente webhook register\|list\|delete`               | Manage push delivery to your endpoint                                             |
| `sente register <appUrl> --identity <ref>`           | Sign up at a third-party app under the identity                                   |
| `sente registrations`                                | List accounts and their latest run status                                         |
| `sente relogin <registrationId>`                     | Re-authenticate an existing account                                               |
| `sente credentials <registrationId>`                 | Print an account's vaulted login (created accounts only)                          |
| `sente connect <appUrl> --identity <ref>`            | Connect an account you already own                                                |
| `sente connections`                                  | List connected accounts                                                           |
| `sente connection revoke\|delete <id>`               | Withdraw a connection / also purge its credentials                                |
| `sente run show\|resume\|abort <runId>`              | Inspect and control a run                                                         |
| `sente watch`                                        | Desktop-notify when a run needs a human                                           |
| `sente session open\|close\|export <registrationId>` | Open, close, or export a logged-in browser session                                |

SDKs for the same API: [TypeScript](/sdks/typescript) · [Python](/sdks/python). Endpoint
details: [API reference](/api-reference/overview).
