From 81f9093c3ce617d75d26a533cc0fbdd94caba3d4 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 10 Jan 2026 16:36:43 +0100 Subject: [PATCH] fix(pairing): accept positional provider args --- CHANGELOG.md | 3 +- README.md | 2 +- docs/cli/index.md | 4 +-- docs/gateway/configuration.md | 4 +-- docs/gateway/security.md | 4 +-- docs/gateway/troubleshooting.md | 2 +- docs/providers/discord.md | 2 +- docs/providers/imessage.md | 4 +-- docs/providers/signal.md | 4 +-- docs/providers/slack.md | 2 +- docs/providers/telegram.md | 4 +-- docs/providers/whatsapp.md | 4 +-- docs/start/faq.md | 4 +-- docs/start/getting-started.md | 4 +-- docs/start/pairing.md | 4 +-- docs/start/wizard.md | 2 +- src/cli/pairing-cli.test.ts | 42 ++++++++++++++++++++++++- src/cli/pairing-cli.ts | 47 +++++++++++++++++++--------- src/commands/doctor-security.ts | 12 +++---- src/commands/onboard-providers.ts | 4 +-- src/pairing/pairing-messages.test.ts | 2 +- src/pairing/pairing-messages.ts | 2 +- src/telegram/bot.ts | 2 +- 23 files changed, 112 insertions(+), 52 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d0160a4d..6a3d4c946 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - Auth: update Claude Code keychain credentials in-place during refresh sync; extract CLI sync helpers + coverage. - Onboarding/Gateway: persist non-interactive gateway token auth in config; add WS wizard + gateway tool-calling regression coverage. - CLI: `clawdbot sessions` now includes `elev:*` + `usage:*` flags in the table output. +- CLI/Pairing: accept positional provider for `pairing list|approve` (npm-run compatible); update docs/bot hints. - Branding: normalize user-facing “ClawdBot”/“CLAWDBOT” → “Clawdbot” (CLI, status, docs). - Doctor: avoid false legacy workspace warning when install dir is `~/clawdbot`. (#660) - iMessage: fix reasoning persistence across DMs; avoid partial/duplicate replies when reasoning is enabled. (#655) — thanks @antons. @@ -91,7 +92,7 @@ - Previously, if you didn’t configure an allowlist, your bot could be **open to anyone** (especially discoverable Telegram bots). - New default: DM pairing (`dmPolicy="pairing"` / `discord.dm.policy="pairing"` / `slack.dm.policy="pairing"`). - To keep old “open to everyone” behavior: set `dmPolicy="open"` and include `"*"` in the relevant `allowFrom` (Discord/Slack: `discord.dm.allowFrom` / `slack.dm.allowFrom`). - - Approve requests via `clawdbot pairing list --provider ` + `clawdbot pairing approve --provider `. + - Approve requests via `clawdbot pairing list ` + `clawdbot pairing approve `. - Sandbox: default `agent.sandbox.scope` to `"agent"` (one container/workspace per agent). Use `"session"` for per-session isolation; `"shared"` disables cross-session isolation. - Timestamps in agent envelopes are now UTC (compact `YYYY-MM-DDTHH:mmZ`); removed `messages.timestampPrefix`. Add `agent.userTimezone` to tell the model the user’s local time (system prompt only). - Model config schema changes (auth profiles + model lists); doctor auto-migrates and the gateway rewrites legacy configs on startup. diff --git a/README.md b/README.md index 0269ec4ad..4f8f45bf4 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ Full security guide: [Security](https://docs.clawd.bot/security) Default behavior on Telegram/WhatsApp/Signal/iMessage/Discord/Slack: - **DM pairing** (`dmPolicy="pairing"` / `discord.dm.policy="pairing"` / `slack.dm.policy="pairing"`): unknown senders receive a short pairing code and the bot does not process their message. -- Approve with: `clawdbot pairing approve --provider ` (then the sender is added to a local allowlist store). +- Approve with: `clawdbot pairing approve ` (then the sender is added to a local allowlist store). - Public inbound DMs require an explicit opt-in: set `dmPolicy="open"` and include `"*"` in the provider allowlist (`allowFrom` / `discord.dm.allowFrom` / `slack.dm.allowFrom`). Run `clawdbot doctor` to surface risky/misconfigured DM policies. diff --git a/docs/cli/index.md b/docs/cli/index.md index d73979756..f77d973c7 100644 --- a/docs/cli/index.md +++ b/docs/cli/index.md @@ -285,8 +285,8 @@ Tip: use `npx clawdhub` to search, install, and sync skills. Approve DM pairing requests across providers. Subcommands: -- `pairing list --provider [--json]` -- `pairing approve --provider <...> [--notify]` +- `pairing list [--json]` +- `pairing approve [--notify]` ### `hooks gmail` Gmail Pub/Sub hook setup + runner. See [/automation/gmail-pubsub](/automation/gmail-pubsub). diff --git a/docs/gateway/configuration.md b/docs/gateway/configuration.md index 7e97a3273..8ce128e13 100644 --- a/docs/gateway/configuration.md +++ b/docs/gateway/configuration.md @@ -251,8 +251,8 @@ Controls how WhatsApp direct chats (DMs) are handled: Pairing codes expire after 1 hour; the bot only sends a pairing code when a new request is created. Pending DM pairing requests are capped at **3 per provider** by default. Pairing approvals: -- `clawdbot pairing list --provider whatsapp` -- `clawdbot pairing approve --provider whatsapp ` +- `clawdbot pairing list whatsapp` +- `clawdbot pairing approve whatsapp ` ### `whatsapp.allowFrom` diff --git a/docs/gateway/security.md b/docs/gateway/security.md index 3de090a88..c8ab737b5 100644 --- a/docs/gateway/security.md +++ b/docs/gateway/security.md @@ -46,8 +46,8 @@ All current DM-capable providers support a DM policy (`dmPolicy` or `*.dm.policy Approve via CLI: ```bash -clawdbot pairing list --provider -clawdbot pairing approve --provider +clawdbot pairing list +clawdbot pairing approve ``` Details + files on disk: [Pairing](/start/pairing) diff --git a/docs/gateway/troubleshooting.md b/docs/gateway/troubleshooting.md index 592d326cb..9808a3f6b 100644 --- a/docs/gateway/troubleshooting.md +++ b/docs/gateway/troubleshooting.md @@ -175,7 +175,7 @@ If `dmPolicy` is `pairing`, unknown senders should receive a code and their mess **Check 1:** Is a pending request already waiting? ```bash -clawdbot pairing list --provider +clawdbot pairing list ``` Pending DM pairing requests are capped at **3 per provider** by default. If the list is full, new requests won’t generate a code until one is approved or expires. diff --git a/docs/providers/discord.md b/docs/providers/discord.md index 1ec08c00c..e2b8cb563 100644 --- a/docs/providers/discord.md +++ b/docs/providers/discord.md @@ -22,7 +22,7 @@ Status: ready for DM and guild text channels via the official Discord bot gatewa - If you prefer env vars, still add `discord: { enabled: true }` to `~/.clawdbot/clawdbot.json` and set `DISCORD_BOT_TOKEN`. 5. Direct chats: use `user:` (or a `<@id>` mention) when delivering; all turns land in the shared `main` session. Bare numeric IDs are ambiguous and rejected. 6. Guild channels: use `channel:` for delivery. Mentions are required by default and can be set per guild or per channel. -7. Direct chats: secure by default via `discord.dm.policy` (default: `"pairing"`). Unknown senders get a pairing code (expires after 1 hour); approve via `clawdbot pairing approve --provider discord `. +7. Direct chats: secure by default via `discord.dm.policy` (default: `"pairing"`). Unknown senders get a pairing code (expires after 1 hour); approve via `clawdbot pairing approve discord `. - To keep old “open to anyone” behavior: set `discord.dm.policy="open"` and `discord.dm.allowFrom=["*"]`. - To hard-allowlist: set `discord.dm.policy="allowlist"` and list senders in `discord.dm.allowFrom`. - To ignore all DMs: set `discord.dm.enabled=false` or `discord.dm.policy="disabled"`. diff --git a/docs/providers/imessage.md b/docs/providers/imessage.md index 9e178032d..fd8a82865 100644 --- a/docs/providers/imessage.md +++ b/docs/providers/imessage.md @@ -86,8 +86,8 @@ DMs: - Default: `imessage.dmPolicy = "pairing"`. - Unknown senders receive a pairing code; messages are ignored until approved (codes expire after 1 hour). - Approve via: - - `clawdbot pairing list --provider imessage` - - `clawdbot pairing approve --provider imessage ` + - `clawdbot pairing list imessage` + - `clawdbot pairing approve imessage ` - Pairing is the default token exchange for iMessage DMs. Details: [Pairing](/start/pairing) Groups: diff --git a/docs/providers/signal.md b/docs/providers/signal.md index a3de20eac..41f1fc538 100644 --- a/docs/providers/signal.md +++ b/docs/providers/signal.md @@ -45,8 +45,8 @@ DMs: - Default: `signal.dmPolicy = "pairing"`. - Unknown senders receive a pairing code; messages are ignored until approved (codes expire after 1 hour). - Approve via: - - `clawdbot pairing list --provider signal` - - `clawdbot pairing approve --provider signal ` + - `clawdbot pairing list signal` + - `clawdbot pairing approve signal ` - Pairing is the default token exchange for Signal DMs. Details: [Pairing](/start/pairing) - UUID-only senders (from `sourceUuid`) are stored as `uuid:` in `signal.allowFrom`. diff --git a/docs/providers/slack.md b/docs/providers/slack.md index 927030b57..20eea4f41 100644 --- a/docs/providers/slack.md +++ b/docs/providers/slack.md @@ -224,7 +224,7 @@ For fine-grained control, use these tags in agent responses: ## DM security (pairing) - Default: `slack.dm.policy="pairing"` — unknown DM senders get a pairing code (expires after 1 hour). -- Approve via: `clawdbot pairing approve --provider slack `. +- Approve via: `clawdbot pairing approve slack `. - To allow anyone: set `slack.dm.policy="open"` and `slack.dm.allowFrom=["*"]`. ## Group policy diff --git a/docs/providers/telegram.md b/docs/providers/telegram.md index 2a8a00165..a669e4e56 100644 --- a/docs/providers/telegram.md +++ b/docs/providers/telegram.md @@ -151,8 +151,8 @@ Private topics (DM forum mode) also include `message_thread_id`. Clawdbot: ### DM access - Default: `telegram.dmPolicy = "pairing"`. Unknown senders receive a pairing code; messages are ignored until approved (codes expire after 1 hour). - Approve via: - - `clawdbot pairing list --provider telegram` - - `clawdbot pairing approve --provider telegram ` + - `clawdbot pairing list telegram` + - `clawdbot pairing approve telegram ` - Pairing is the default token exchange used for Telegram DMs. Details: [Pairing](/start/pairing) ### Group access diff --git a/docs/providers/whatsapp.md b/docs/providers/whatsapp.md index 9828c75d0..dc05b6874 100644 --- a/docs/providers/whatsapp.md +++ b/docs/providers/whatsapp.md @@ -39,7 +39,7 @@ Use a **separate phone number** for Clawdbot. Best UX, clean routing, no self-ch **Pairing mode (optional):** If you want pairing instead of allowlist, set `whatsapp.dmPolicy` to `pairing`. Unknown senders get a pairing code; approve with: -`clawdbot pairing approve --provider whatsapp ` +`clawdbot pairing approve whatsapp ` ### Personal number (fallback) Quick fallback: run Clawdbot on **your own number**. Message yourself (WhatsApp “Message yourself”) for testing so you don’t spam contacts. Expect to read verification codes on your main phone during setup and experiments. **Must enable self-chat mode.** @@ -95,7 +95,7 @@ on outbound replies. - Status/broadcast chats are ignored. - Direct chats use E.164; groups use group JID. - **DM policy**: `whatsapp.dmPolicy` controls direct chat access (default: `pairing`). - - Pairing: unknown senders get a pairing code (approve via `clawdbot pairing approve --provider whatsapp `; codes expire after 1 hour). + - Pairing: unknown senders get a pairing code (approve via `clawdbot pairing approve whatsapp `; codes expire after 1 hour). - Open: requires `whatsapp.allowFrom` to include `"*"`. - Self messages are always allowed; “self-chat mode” still requires `whatsapp.allowFrom` to include your own number. diff --git a/docs/start/faq.md b/docs/start/faq.md index d2f5695d7..339d5495a 100644 --- a/docs/start/faq.md +++ b/docs/start/faq.md @@ -631,8 +631,8 @@ Treat inbound DMs as untrusted input. Defaults are designed to reduce risk: - Default behavior on DM‑capable providers is **pairing**: - Unknown senders receive a pairing code; the bot does not process their message. - - Approve with: `clawdbot pairing approve --provider ` - - Pending requests are capped at **3 per provider**; check `clawdbot pairing list --provider ` if a code didn’t arrive. + - Approve with: `clawdbot pairing approve ` + - Pending requests are capped at **3 per provider**; check `clawdbot pairing list ` if a code didn’t arrive. - Opening DMs publicly requires explicit opt‑in (`dmPolicy: "open"` and allowlist `"*"`). Run `clawdbot doctor` to surface risky DM policies. diff --git a/docs/start/getting-started.md b/docs/start/getting-started.md index e7197f901..b141821dc 100644 --- a/docs/start/getting-started.md +++ b/docs/start/getting-started.md @@ -128,8 +128,8 @@ Default posture: unknown DMs get a short code and messages are not processed unt If your first DM gets no reply, approve the pairing: ```bash -clawdbot pairing list --provider whatsapp -clawdbot pairing approve --provider whatsapp +clawdbot pairing list whatsapp +clawdbot pairing approve whatsapp ``` Pairing doc: [Pairing](/start/pairing) diff --git a/docs/start/pairing.md b/docs/start/pairing.md index 79454928a..4f9c43dd3 100644 --- a/docs/start/pairing.md +++ b/docs/start/pairing.md @@ -30,8 +30,8 @@ Pairing codes: ### Approve a sender ```bash -clawdbot pairing list --provider telegram -clawdbot pairing approve --provider telegram +clawdbot pairing list telegram +clawdbot pairing approve telegram ``` Supported providers: `telegram`, `whatsapp`, `signal`, `imessage`, `discord`, `slack`. diff --git a/docs/start/wizard.md b/docs/start/wizard.md index 25b60cc46..0aa1786a8 100644 --- a/docs/start/wizard.md +++ b/docs/start/wizard.md @@ -103,7 +103,7 @@ Tip: `--json` does **not** imply non-interactive mode. Use `--non-interactive` ( - Discord: bot token. - Signal: optional `signal-cli` install + account config. - iMessage: local `imsg` CLI path + DB access. - - DM security: default is pairing. First DM sends a code; approve via `clawdbot pairing approve --provider ` or use allowlists. + - DM security: default is pairing. First DM sends a code; approve via `clawdbot pairing approve ` or use allowlists. 6) **Daemon install** - macOS: LaunchAgent diff --git a/src/cli/pairing-cli.test.ts b/src/cli/pairing-cli.test.ts index 887ada6b0..08bf99954 100644 --- a/src/cli/pairing-cli.test.ts +++ b/src/cli/pairing-cli.test.ts @@ -2,10 +2,11 @@ import { Command } from "commander"; import { describe, expect, it, vi } from "vitest"; const listProviderPairingRequests = vi.fn(); +const approveProviderPairingCode = vi.fn(); vi.mock("../pairing/pairing-store.js", () => ({ listProviderPairingRequests, - approveProviderPairingCode: vi.fn(), + approveProviderPairingCode, })); vi.mock("../telegram/send.js", () => ({ @@ -61,6 +62,18 @@ describe("pairing cli", () => { ); }); + it("accepts provider as positional for list", async () => { + const { registerPairingCli } = await import("./pairing-cli.js"); + listProviderPairingRequests.mockResolvedValueOnce([]); + + const program = new Command(); + program.name("test"); + registerPairingCli(program); + await program.parseAsync(["pairing", "list", "telegram"], { from: "user" }); + + expect(listProviderPairingRequests).toHaveBeenCalledWith("telegram"); + }); + it("labels Discord ids as discordUserId", async () => { const { registerPairingCli } = await import("./pairing-cli.js"); listProviderPairingRequests.mockResolvedValueOnce([ @@ -84,4 +97,31 @@ describe("pairing cli", () => { expect.stringContaining("discordUserId=999"), ); }); + + it("accepts provider as positional for approve (npm-run compatible)", async () => { + const { registerPairingCli } = await import("./pairing-cli.js"); + approveProviderPairingCode.mockResolvedValueOnce({ + id: "123", + entry: { + id: "123", + code: "ABCDEFGH", + createdAt: "2026-01-08T00:00:00Z", + lastSeenAt: "2026-01-08T00:00:00Z", + }, + }); + + const log = vi.spyOn(console, "log").mockImplementation(() => {}); + const program = new Command(); + program.name("test"); + registerPairingCli(program); + await program.parseAsync(["pairing", "approve", "telegram", "ABCDEFGH"], { + from: "user", + }); + + expect(approveProviderPairingCode).toHaveBeenCalledWith({ + provider: "telegram", + code: "ABCDEFGH", + }); + expect(log).toHaveBeenCalledWith(expect.stringContaining("Approved")); + }); }); diff --git a/src/cli/pairing-cli.ts b/src/cli/pairing-cli.ts index be6ac1dc3..b6860e85b 100644 --- a/src/cli/pairing-cli.ts +++ b/src/cli/pairing-cli.ts @@ -83,13 +83,17 @@ export function registerPairingCli(program: Command) { pairing .command("list") .description("List pending pairing requests") - .requiredOption( - "--provider ", - `Provider (${PROVIDERS.join(", ")})`, - ) + .option("--provider ", `Provider (${PROVIDERS.join(", ")})`) + .argument("[provider]", `Provider (${PROVIDERS.join(", ")})`) .option("--json", "Print JSON", false) - .action(async (opts) => { - const provider = parseProvider(opts.provider); + .action(async (providerArg, opts) => { + const providerRaw = opts.provider ?? providerArg; + if (!providerRaw) { + throw new Error( + `Provider required. Use --provider or pass it as the first argument (expected one of: ${PROVIDERS.join(", ")})`, + ); + } + const provider = parseProvider(providerRaw); const requests = await listProviderPairingRequests(provider); if (opts.json) { console.log(JSON.stringify({ provider, requests }, null, 2)); @@ -111,20 +115,35 @@ export function registerPairingCli(program: Command) { pairing .command("approve") .description("Approve a pairing code and allow that sender") - .requiredOption( - "--provider ", - `Provider (${PROVIDERS.join(", ")})`, + .option("--provider ", `Provider (${PROVIDERS.join(", ")})`) + .argument( + "", + "Pairing code (or provider when using 2 args)", ) - .argument("", "Pairing code (shown to the requester)") + .argument("[code]", "Pairing code (when provider is passed as the 1st arg)") .option("--notify", "Notify the requester on the same provider", false) - .action(async (code, opts) => { - const provider = parseProvider(opts.provider); + .action(async (codeOrProvider, code, opts) => { + const providerRaw = opts.provider ?? codeOrProvider; + const resolvedCode = opts.provider ? codeOrProvider : code; + if (!opts.provider && !code) { + throw new Error( + `Usage: clawdbot pairing approve (or: clawdbot pairing approve --provider )`, + ); + } + if (opts.provider && code != null) { + throw new Error( + `Too many arguments. Use: clawdbot pairing approve --provider `, + ); + } + const provider = parseProvider(providerRaw); const approved = await approveProviderPairingCode({ provider, - code: String(code), + code: String(resolvedCode), }); if (!approved) { - throw new Error(`No pending pairing request found for code: ${code}`); + throw new Error( + `No pending pairing request found for code: ${String(resolvedCode)}`, + ); } console.log(`Approved ${provider} sender ${approved.id}.`); diff --git a/src/commands/doctor-security.ts b/src/commands/doctor-security.ts index 7d529e5d9..1f593c429 100644 --- a/src/commands/doctor-security.ts +++ b/src/commands/doctor-security.ts @@ -115,7 +115,7 @@ export async function noteSecurityWarnings(cfg: ClawdbotConfig) { `- Telegram DMs: locked (telegram.dmPolicy="${dmPolicy}") with no allowlist; unknown senders will be blocked / get a pairing code.`, ); warnings.push( - ` Approve via: clawdbot pairing list --provider telegram / clawdbot pairing approve --provider telegram `, + ` Approve via: clawdbot pairing list telegram / clawdbot pairing approve telegram `, ); } @@ -137,7 +137,7 @@ export async function noteSecurityWarnings(cfg: ClawdbotConfig) { allowFrom: cfg.discord?.dm?.allowFrom ?? [], allowFromPath: "discord.dm.", approveHint: - "Approve via: clawdbot pairing list --provider discord / clawdbot pairing approve --provider discord ", + "Approve via: clawdbot pairing list discord / clawdbot pairing approve discord ", normalizeEntry: (raw) => raw.replace(/^(discord|user):/i, "").replace(/^<@!?(\d+)>$/, "$1"), }); @@ -151,7 +151,7 @@ export async function noteSecurityWarnings(cfg: ClawdbotConfig) { allowFrom: cfg.slack?.dm?.allowFrom ?? [], allowFromPath: "slack.dm.", approveHint: - "Approve via: clawdbot pairing list --provider slack / clawdbot pairing approve --provider slack ", + "Approve via: clawdbot pairing list slack / clawdbot pairing approve slack ", normalizeEntry: (raw) => raw.replace(/^(slack|user):/i, ""), }); } @@ -164,7 +164,7 @@ export async function noteSecurityWarnings(cfg: ClawdbotConfig) { allowFrom: cfg.signal?.allowFrom ?? [], allowFromPath: "signal.", approveHint: - "Approve via: clawdbot pairing list --provider signal / clawdbot pairing approve --provider signal ", + "Approve via: clawdbot pairing list signal / clawdbot pairing approve signal ", normalizeEntry: (raw) => normalizeE164(raw.replace(/^signal:/i, "").trim()), }); @@ -178,7 +178,7 @@ export async function noteSecurityWarnings(cfg: ClawdbotConfig) { allowFrom: cfg.imessage?.allowFrom ?? [], allowFromPath: "imessage.", approveHint: - "Approve via: clawdbot pairing list --provider imessage / clawdbot pairing approve --provider imessage ", + "Approve via: clawdbot pairing list imessage / clawdbot pairing approve imessage ", }); } @@ -190,7 +190,7 @@ export async function noteSecurityWarnings(cfg: ClawdbotConfig) { allowFrom: cfg.whatsapp?.allowFrom ?? [], allowFromPath: "whatsapp.", approveHint: - "Approve via: clawdbot pairing list --provider whatsapp / clawdbot pairing approve --provider whatsapp ", + "Approve via: clawdbot pairing list whatsapp / clawdbot pairing approve whatsapp ", normalizeEntry: (raw) => normalizeE164(raw), }); } diff --git a/src/commands/onboard-providers.ts b/src/commands/onboard-providers.ts index 60cd3de7a..30258dcce 100644 --- a/src/commands/onboard-providers.ts +++ b/src/commands/onboard-providers.ts @@ -123,7 +123,7 @@ async function noteProviderPrimer(prompter: WizardPrompter): Promise { await prompter.note( [ "DM security: default is pairing; unknown DMs get a pairing code.", - "Approve with: clawdbot pairing approve --provider ", + "Approve with: clawdbot pairing approve ", 'Public DMs require dmPolicy="open" + allowFrom=["*"].', `Docs: ${formatDocsLink("/start/pairing", "start/pairing")}`, "", @@ -401,7 +401,7 @@ async function maybeConfigureDmPolicies(params: { await prompter.note( [ "Default: pairing (unknown DMs get a pairing code).", - `Approve: clawdbot pairing approve --provider ${params.provider} `, + `Approve: clawdbot pairing approve ${params.provider} `, `Public DMs: ${params.policyKey}="open" + ${params.allowFromKey} includes "*".`, `Docs: ${formatDocsLink("/start/pairing", "start/pairing")}`, ].join("\n"), diff --git a/src/pairing/pairing-messages.test.ts b/src/pairing/pairing-messages.test.ts index 8bfa1e6f9..c9679b73d 100644 --- a/src/pairing/pairing-messages.test.ts +++ b/src/pairing/pairing-messages.test.ts @@ -37,7 +37,7 @@ describe("buildPairingReply", () => { expect(text).toContain(testCase.idLine); expect(text).toContain(`Pairing code: ${testCase.code}`); expect(text).toContain( - `clawdbot pairing approve --provider ${testCase.provider} `, + `clawdbot pairing approve ${testCase.provider} `, ); }); } diff --git a/src/pairing/pairing-messages.ts b/src/pairing/pairing-messages.ts index 2569d6bc8..c7d5a8528 100644 --- a/src/pairing/pairing-messages.ts +++ b/src/pairing/pairing-messages.ts @@ -14,6 +14,6 @@ export function buildPairingReply(params: { `Pairing code: ${code}`, "", "Ask the bot owner to approve with:", - `clawdbot pairing approve --provider ${provider} `, + `clawdbot pairing approve ${provider} `, ].join("\n"); } diff --git a/src/telegram/bot.ts b/src/telegram/bot.ts index a0b6170bb..0d8ddda8b 100644 --- a/src/telegram/bot.ts +++ b/src/telegram/bot.ts @@ -496,7 +496,7 @@ export function createTelegramBot(opts: TelegramBotOptions) { `Pairing code: ${code}`, "", "Ask the bot owner to approve with:", - "clawdbot pairing approve --provider telegram ", + "clawdbot pairing approve telegram ", ].join("\n"), ); }