feat: add onboarding doc links

This commit is contained in:
Peter Steinberger
2026-01-07 01:19:31 +01:00
parent 19c95d0ff7
commit 62112d9978
7 changed files with 110 additions and 21 deletions

View File

@@ -1194,6 +1194,12 @@ Control UI base path:
- Examples: `"/ui"`, `"/clawdbot"`, `"/apps/clawdbot"`.
- Default: root (`/`) (unchanged).
Related docs:
- [Control UI](/web/control-ui)
- [Web overview](/web)
- [Tailscale](/gateway/tailscale)
- [Remote access](/gateway/remote)
Notes:
- `clawdbot gateway` refuses to start unless `gateway.mode` is set to `local` (or you pass the override flag).
- `gateway.port` controls the single multiplexed port used for WebSocket + HTTP (control UI, hooks, A2UI).

View File

@@ -150,6 +150,14 @@ async function promptGatewayConfig(
let tailscaleResetOnExit = false;
if (tailscaleMode !== "off") {
note(
[
"Docs:",
"https://docs.clawd.bot/gateway/tailscale",
"https://docs.clawd.bot/web",
].join("\n"),
"Tailscale",
);
tailscaleResetOnExit = Boolean(
guardCancel(
await confirm({
@@ -300,6 +308,7 @@ async function promptAuthConfig(
} catch (err) {
spin.stop("OAuth failed");
runtime.error(String(err));
note("Trouble with OAuth? See https://docs.clawd.bot/start/faq", "OAuth");
}
} else if (authChoice === "openai-codex") {
const isRemote = isRemoteEnvironment();
@@ -373,6 +382,7 @@ async function promptAuthConfig(
} catch (err) {
spin.stop("OpenAI OAuth failed");
runtime.error(String(err));
note("Trouble with OAuth? See https://docs.clawd.bot/start/faq", "OAuth");
}
} else if (authChoice === "antigravity") {
const isRemote = isRemoteEnvironment();
@@ -447,6 +457,7 @@ async function promptAuthConfig(
} catch (err) {
spin.stop("Antigravity OAuth failed");
runtime.error(String(err));
note("Trouble with OAuth? See https://docs.clawd.bot/start/faq", "OAuth");
}
} else if (authChoice === "apiKey") {
const key = guardCancel(
@@ -608,9 +619,11 @@ export async function runConfigureWizard(
note(summarizeExistingConfig(baseConfig), title);
if (!snapshot.valid && snapshot.issues.length > 0) {
note(
snapshot.issues
.map((iss) => `- ${iss.path}: ${iss.message}`)
.join("\n"),
[
...snapshot.issues.map((iss) => `- ${iss.path}: ${iss.message}`),
"",
"Docs: https://docs.clawd.bot/gateway/configuration",
].join("\n"),
"Config issues",
);
}
@@ -789,6 +802,14 @@ export async function runConfigureWizard(
await healthCommand({ json: false, timeoutMs: 10_000 }, runtime);
} catch (err) {
runtime.error(`Health check failed: ${String(err)}`);
note(
[
"Docs:",
"https://docs.clawd.bot/gateway/health",
"https://docs.clawd.bot/gateway/troubleshooting",
].join("\n"),
"Health check help",
);
}
}
@@ -797,20 +818,22 @@ export async function runConfigureWizard(
runtime.error(controlUiAssets.message);
}
note(
(() => {
const bind = nextConfig.gateway?.bind ?? "loopback";
const links = resolveControlUiLinks({
bind,
port: gatewayPort,
basePath: nextConfig.gateway?.controlUi?.basePath,
});
return [`Web UI: ${links.httpUrl}`, `Gateway WS: ${links.wsUrl}`].join(
"\n",
);
})(),
"Control UI",
);
note(
(() => {
const bind = nextConfig.gateway?.bind ?? "loopback";
const links = resolveControlUiLinks({
bind,
port: gatewayPort,
basePath: nextConfig.gateway?.controlUi?.basePath,
});
return [
`Web UI: ${links.httpUrl}`,
`Gateway WS: ${links.wsUrl}`,
"Docs: https://docs.clawd.bot/web/control-ui",
].join("\n");
})(),
"Control UI",
);
const browserSupport = await detectBrowserOpenSupport();
if (!browserSupport.ok) {

View File

@@ -195,6 +195,9 @@ export function formatControlUiSshHint(params: {
"Then open:",
localUrl,
authedUrl,
"Docs:",
"https://docs.clawd.bot/gateway/remote",
"https://docs.clawd.bot/web/control-ui",
]
.filter(Boolean)
.join("\n");

View File

@@ -39,6 +39,7 @@ async function noteProviderPrimer(prompter: WizardPrompter): Promise<void> {
"DM security: default is pairing; unknown DMs get a pairing code.",
"Approve with: clawdbot pairing approve --provider <provider> <code>",
'Public DMs require dmPolicy="open" + allowFrom=["*"].',
"Docs: https://docs.clawd.bot/start/pairing",
"",
"WhatsApp: links via WhatsApp Web (scan QR), stores creds for future sends.",
"WhatsApp: dedicated second number recommended; primary number OK (self-chat).",
@@ -59,6 +60,7 @@ async function noteTelegramTokenHelp(prompter: WizardPrompter): Promise<void> {
"2) Run /newbot (or /mybots)",
"3) Copy the token (looks like 123456:ABC...)",
"Tip: you can also set TELEGRAM_BOT_TOKEN in your env.",
"Docs: https://docs.clawd.bot/telegram",
].join("\n"),
"Telegram bot token",
);
@@ -71,6 +73,7 @@ async function noteDiscordTokenHelp(prompter: WizardPrompter): Promise<void> {
"2) Bot → Add Bot → Reset Token → copy token",
"3) OAuth2 → URL Generator → scope 'bot' → invite to your server",
"Tip: enable Message Content Intent if you need message text.",
"Docs: https://docs.clawd.bot/discord",
].join("\n"),
"Discord bot token",
);
@@ -158,6 +161,7 @@ async function noteSlackTokenHelp(
"4) Enable Event Subscriptions (socket) for message events",
"5) App Home → enable the Messages tab for DMs",
"Tip: set SLACK_BOT_TOKEN + SLACK_APP_TOKEN in your env.",
"Docs: https://docs.clawd.bot/slack",
"",
"Manifest (JSON):",
manifest,
@@ -298,6 +302,7 @@ async function maybeConfigureDmPolicies(params: {
"Default: pairing (unknown DMs get a pairing code).",
`Approve: clawdbot pairing approve --provider ${params.provider} <code>`,
`Public DMs: ${params.policyKey}="open" + ${params.allowFromKey} includes "*".`,
"Docs: https://docs.clawd.bot/start/pairing",
].join("\n"),
`${params.label} DM access`,
);
@@ -383,6 +388,7 @@ async function promptWhatsAppAllowFrom(
"- disabled: ignore WhatsApp DMs",
"",
`Current: dmPolicy=${existingPolicy}, allowFrom=${existingLabel}`,
"Docs: https://docs.clawd.bot/whatsapp",
].join("\n"),
"WhatsApp DM access",
);
@@ -551,6 +557,7 @@ export async function setupProviders(
[
"Scan the QR with WhatsApp on your phone.",
`Credentials are stored under ${WA_WEB_AUTH_DIR}/ for future runs.`,
"Docs: https://docs.clawd.bot/whatsapp",
].join("\n"),
"WhatsApp linking",
);
@@ -566,6 +573,10 @@ export async function setupProviders(
await loginWeb(false, "web");
} catch (err) {
runtime.error(`WhatsApp login failed: ${String(err)}`);
await prompter.note(
"Docs: https://docs.clawd.bot/whatsapp",
"WhatsApp help",
);
}
} else if (!whatsappLinked) {
await prompter.note(
@@ -864,6 +875,7 @@ export async function setupProviders(
'Link device with: signal-cli link -n "Clawdbot"',
"Scan QR in Signal → Linked Devices",
"Then run: clawdbot gateway call providers.status --params '{\"probe\":true}'",
"Docs: https://docs.clawd.bot/signal",
].join("\n"),
"Signal next steps",
);
@@ -902,6 +914,7 @@ export async function setupProviders(
"Ensure Clawdbot has Full Disk Access to Messages DB.",
"Grant Automation permission for Messages when prompted.",
"List chats with: imsg chats --limit 20",
"Docs: https://docs.clawd.bot/imessage",
].join("\n"),
"iMessage next steps",
);

View File

@@ -42,7 +42,10 @@ export async function promptRemoteGatewayConfig(
if (!hasBonjourTool) {
await prompter.note(
"Bonjour discovery requires dns-sd (macOS) or avahi-browse (Linux).",
[
"Bonjour discovery requires dns-sd (macOS) or avahi-browse (Linux).",
"Docs: https://docs.clawd.bot/gateway/discovery",
].join("\n"),
"Discovery",
);
}
@@ -98,6 +101,7 @@ export async function promptRemoteGatewayConfig(
`ssh -N -L 18789:127.0.0.1:18789 <user>@${host}${
selectedBeacon.sshPort ? ` -p ${selectedBeacon.sshPort}` : ""
}`,
"Docs: https://docs.clawd.bot/gateway/remote",
].join("\n"),
"SSH tunnel",
);

View File

@@ -168,6 +168,7 @@ export async function setupSkills(
runtime.log(
"Tip: run `clawdbot doctor` to review skills + requirements.",
);
runtime.log("Docs: https://docs.clawd.bot/skills");
}
}
}

View File

@@ -142,9 +142,11 @@ export async function runOnboardingWizard(
await prompter.note(summarizeExistingConfig(baseConfig), title);
if (!snapshot.valid && snapshot.issues.length > 0) {
await prompter.note(
snapshot.issues
.map((iss) => `- ${iss.path}: ${iss.message}`)
.join("\n"),
[
...snapshot.issues.map((iss) => `- ${iss.path}: ${iss.message}`),
"",
"Docs: https://docs.clawd.bot/gateway/configuration",
].join("\n"),
"Config issues",
);
}
@@ -302,6 +304,10 @@ export async function runOnboardingWizard(
} catch (err) {
spin.stop("OAuth failed");
runtime.error(String(err));
await prompter.note(
"Trouble with OAuth? See https://docs.clawd.bot/start/faq",
"OAuth help",
);
}
} else if (authChoice === "openai-codex") {
const isRemote = isRemoteEnvironment();
@@ -375,6 +381,10 @@ export async function runOnboardingWizard(
} catch (err) {
spin.stop("OpenAI OAuth failed");
runtime.error(String(err));
await prompter.note(
"Trouble with OAuth? See https://docs.clawd.bot/start/faq",
"OAuth help",
);
}
} else if (authChoice === "antigravity") {
const isRemote = isRemoteEnvironment();
@@ -448,6 +458,10 @@ export async function runOnboardingWizard(
} catch (err) {
spin.stop("Antigravity OAuth failed");
runtime.error(String(err));
await prompter.note(
"Trouble with OAuth? See https://docs.clawd.bot/start/faq",
"OAuth help",
);
}
} else if (authChoice === "apiKey") {
const key = await prompter.text({
@@ -520,6 +534,14 @@ export async function runOnboardingWizard(
let tailscaleResetOnExit = false;
if (tailscaleMode !== "off") {
await prompter.note(
[
"Docs:",
"https://docs.clawd.bot/gateway/tailscale",
"https://docs.clawd.bot/web",
].join("\n"),
"Tailscale",
);
tailscaleResetOnExit = Boolean(
await prompter.confirm({
message: "Reset Tailscale serve/funnel on exit?",
@@ -693,6 +715,14 @@ export async function runOnboardingWizard(
await healthCommand({ json: false, timeoutMs: 10_000 }, runtime);
} catch (err) {
runtime.error(`Health check failed: ${String(err)}`);
await prompter.note(
[
"Docs:",
"https://docs.clawd.bot/gateway/health",
"https://docs.clawd.bot/gateway/troubleshooting",
].join("\n"),
"Health check help",
);
}
const controlUiAssets = await ensureControlUiAssetsBuilt(runtime);
@@ -726,6 +756,7 @@ export async function runOnboardingWizard(
`Web UI: ${links.httpUrl}`,
tokenParam ? `Web UI (with token): ${authedUrl}` : undefined,
`Gateway WS: ${links.wsUrl}`,
"Docs: https://docs.clawd.bot/web/control-ui",
]
.filter(Boolean)
.join("\n");
@@ -772,5 +803,13 @@ export async function runOnboardingWizard(
}
}
await prompter.note(
[
"Back up your agent workspace.",
"Docs: https://docs.clawd.bot/concepts/agent-workspace",
].join("\n"),
"Workspace backup",
);
await prompter.outro("Onboarding complete.");
}