ui(macos): polish onboarding wording

This commit is contained in:
Peter Steinberger
2025-12-14 19:22:31 +00:00
parent 3d959c46d0
commit fb23717102
2 changed files with 53 additions and 52 deletions

View File

@@ -20,7 +20,7 @@ struct MasterDiscoveryInlineList: View {
}
if self.discovery.masters.isEmpty {
Text("No masters found yet.")
Text("No gateways found yet.")
.font(.caption)
.foregroundStyle(.secondary)
} else {
@@ -86,7 +86,7 @@ struct MasterDiscoveryInlineList: View {
.fill(Color(NSColor.controlBackgroundColor)))
}
}
.help("Click a discovered master to fill the SSH target.")
.help("Click a discovered gateway to fill the SSH target.")
}
private func suggestedSSHTarget(_ gateway: MasterDiscoveryModel.DiscoveredMaster) -> String? {

View File

@@ -212,8 +212,8 @@ struct OnboardingView: View {
Text("Welcome to Clawdis")
.font(.largeTitle.weight(.semibold))
Text(
"Your macOS menu bar companion for notifications, screenshots, and agent automation " +
"setup takes just a few minutes.")
"Your macOS menu bar companion for notifications, screenshots, and agent automation. " +
"Setup takes a few minutes.")
.font(.body)
.foregroundStyle(.secondary)
.multilineTextAlignment(.center)
@@ -255,8 +255,8 @@ struct OnboardingView: View {
Text("Where Clawdis runs")
.font(.largeTitle.weight(.semibold))
Text(
"Clawdis has one primary Gateway (“master”) that runs continuously. " +
"Connect locally or over SSH/Tailscale so the agent can work on any Mac.")
"Clawdis uses a single Gateway (“master”) that stays running. Run it on this Mac, " +
"or connect to one on another Mac over SSH/Tailscale.")
.font(.body)
.foregroundStyle(.secondary)
.multilineTextAlignment(.center)
@@ -265,9 +265,9 @@ struct OnboardingView: View {
.fixedSize(horizontal: false, vertical: true)
self.onboardingCard(spacing: 12, padding: 14) {
Picker("Clawdis runs", selection: self.$state.connectionMode) {
Text("Local (this Mac)").tag(AppState.ConnectionMode.local)
Text("Remote over SSH").tag(AppState.ConnectionMode.remote)
Picker("Gateway runs", selection: self.$state.connectionMode) {
Text("This Mac").tag(AppState.ConnectionMode.local)
Text("Remote (SSH)").tag(AppState.ConnectionMode.remote)
}
.pickerStyle(.segmented)
.frame(width: 360)
@@ -282,7 +282,7 @@ struct OnboardingView: View {
Text("SSH target")
.font(.callout.weight(.semibold))
.frame(width: labelWidth, alignment: .leading)
TextField("user@host[:22]", text: self.$state.remoteTarget)
TextField("user@host[:port]", text: self.$state.remoteTarget)
.textFieldStyle(.roundedBorder)
.frame(width: fieldWidth)
}
@@ -312,7 +312,7 @@ struct OnboardingView: View {
.padding(.top, 4)
}
Text("Tip: enable Tailscale so your remote Clawdis stays reachable.")
Text("Tip: keep Tailscale enabled so your gateway stays reachable.")
.font(.footnote)
.foregroundStyle(.secondary)
.lineLimit(1)
@@ -345,7 +345,7 @@ struct OnboardingView: View {
Circle()
.fill(self.anthropicAuthConnected ? Color.green : Color.orange)
.frame(width: 10, height: 10)
Text(self.anthropicAuthConnected ? "Anthropic OAuth connected" : "Not connected yet")
Text(self.anthropicAuthConnected ? "Claude connected (OAuth)" : "Not connected yet")
.font(.headline)
Spacer()
}
@@ -358,7 +358,7 @@ struct OnboardingView: View {
}
Text(
"This writes Pi-compatible credentials to `~/.pi/agent/oauth.json` (owner-only). " +
"This lets Pi use Claude immediately. Credentials are stored at `~/.pi/agent/oauth.json` (owner-only). " +
"You can redo this anytime.")
.font(.subheadline)
.foregroundStyle(.secondary)
@@ -393,14 +393,14 @@ struct OnboardingView: View {
if self.anthropicAuthBusy {
ProgressView()
} else {
Text("Open Claude login (OAuth)")
Text("Open Claude sign-in (OAuth)")
}
}
.buttonStyle(.borderedProminent)
.disabled(self.anthropicAuthBusy)
Button("Skip for now") {
self.anthropicAuthStatus = "Skipped. The agent may not respond until you authenticate."
self.anthropicAuthStatus = "Skipped. Pi may not respond until you connect Claude."
}
.buttonStyle(.bordered)
.disabled(self.anthropicAuthBusy)
@@ -408,12 +408,12 @@ struct OnboardingView: View {
if self.anthropicAuthPKCE != nil {
VStack(alignment: .leading, spacing: 8) {
Text("Paste `code#state`")
Text("Paste the `code#state` value")
.font(.headline)
TextField("code#state", text: self.$anthropicAuthCode)
.textFieldStyle(.roundedBorder)
Button("Finish connection") {
Button("Connect") {
Task { await self.finishAnthropicOAuth() }
}
.buttonStyle(.bordered)
@@ -427,8 +427,8 @@ struct OnboardingView: View {
Text("API key (advanced)")
.font(.headline)
Text(
"You can also use an Anthropic API key, but this is instructions-only for now " +
"(GUI-launched processes dont automatically inherit your shell env vars).")
"You can also use an Anthropic API key, but this UI is instructions-only for now " +
"(GUI apps dont automatically inherit your shell env vars).")
.font(.subheadline)
.foregroundStyle(.secondary)
.fixedSize(horizontal: false, vertical: true)
@@ -456,7 +456,7 @@ struct OnboardingView: View {
self.anthropicAuthPKCE = pkce
let url = AnthropicOAuth.buildAuthorizeURL(pkce: pkce)
NSWorkspace.shared.open(url)
self.anthropicAuthStatus = "Opened browser. After approving, paste the `code#state` here."
self.anthropicAuthStatus = "Browser opened. After approving, paste the `code#state` value here."
} catch {
self.anthropicAuthStatus = "Failed to start OAuth: \(error.localizedDescription)"
}
@@ -478,7 +478,7 @@ struct OnboardingView: View {
let creds = try await AnthropicOAuth.exchangeCode(code: code, state: state, verifier: pkce.verifier)
try PiOAuthStore.saveAnthropicOAuth(creds)
self.refreshAnthropicOAuthStatus()
self.anthropicAuthStatus = "Connected. Pi can now use Claude via Anthropic OAuth."
self.anthropicAuthStatus = "Connected. Pi can now use Claude."
} catch {
self.anthropicAuthStatus = "OAuth failed: \(error.localizedDescription)"
}
@@ -494,7 +494,7 @@ struct OnboardingView: View {
self.onboardingPage {
Text("Identity")
.font(.largeTitle.weight(.semibold))
Text("Name your agent, pick a theme, and well suggest an emoji.")
Text("Name your agent, pick a vibe, and choose an emoji.")
.font(.body)
.foregroundStyle(.secondary)
.multilineTextAlignment(.center)
@@ -568,8 +568,7 @@ struct OnboardingView: View {
Text(
"This writes your identity to `~/.clawdis/clawdis.json` and into `AGENTS.md` " +
"inside the workspace. " +
"Treat that workspace as the agents “memory” and consider making it a (private) git " +
"repo.")
"Treat that workspace as the agents “memory” and consider making it a private git repo.")
.font(.caption)
.foregroundStyle(.secondary)
.fixedSize(horizontal: false, vertical: true)
@@ -589,10 +588,8 @@ struct OnboardingView: View {
Text("Install the gateway")
.font(.largeTitle.weight(.semibold))
Text(
"""
Clawdis now runs the WebSocket gateway from the global "clawdis" package.
Install/update it here and well check Node for you.
""")
"The Gateway is the WebSocket service that keeps Clawdis connected. " +
"Well install/update the `clawdis` npm package and verify Node is available.")
.font(.body)
.foregroundStyle(.secondary)
.multilineTextAlignment(.center)
@@ -636,7 +633,7 @@ struct OnboardingView: View {
if self.gatewayInstalling {
ProgressView()
} else {
Text("Install / Update gateway")
Text("Install or update gateway")
}
}
.buttonStyle(.borderedProminent)
@@ -654,8 +651,8 @@ struct OnboardingView: View {
.lineLimit(2)
} else {
Text(
"Uses \"npm install -g clawdis@<version>\" on your PATH. " +
"We keep the gateway on port 18789.")
"Runs `npm install -g clawdis@<version>` on your PATH. " +
"The gateway listens on port 18789.")
.font(.caption)
.foregroundStyle(.secondary)
.lineLimit(2)
@@ -681,7 +678,7 @@ struct OnboardingView: View {
self.onboardingPage {
Text("Grant permissions")
.font(.largeTitle.weight(.semibold))
Text("Approve these once and the helper CLI reuses the same grants.")
Text("These macOS permissions let Clawdis automate apps and capture context on this Mac.")
.font(.body)
.foregroundStyle(.secondary)
.multilineTextAlignment(.center)
@@ -718,7 +715,7 @@ struct OnboardingView: View {
self.onboardingPage {
Text("Install the helper CLI")
.font(.largeTitle.weight(.semibold))
Text("Link `clawdis-mac` so scripts and the agent can talk to this app.")
Text("Optional, but recommended: link `clawdis-mac` so scripts can talk to this app.")
.font(.body)
.foregroundStyle(.secondary)
.multilineTextAlignment(.center)
@@ -773,10 +770,8 @@ struct OnboardingView: View {
Text("Agent workspace")
.font(.largeTitle.weight(.semibold))
Text(
"""
Clawdis runs the agent from a dedicated workspace so it can load AGENTS.md
and write files without touching your other folders.
""")
"Clawdis runs the agent from a dedicated workspace so it can load `AGENTS.md` " +
"and write files there without mixing into your other projects.")
.font(.body)
.foregroundStyle(.secondary)
.multilineTextAlignment(.center)
@@ -844,7 +839,7 @@ struct OnboardingView: View {
} else {
Text(
"Tip: edit AGENTS.md in this folder to shape the assistants behavior. " +
"For backup, make the workspace a (private) git repo so Clawds “memory” is versioned.")
"For backup, make the workspace a private git repo so your agents “memory” is versioned.")
.font(.caption)
.foregroundStyle(.secondary)
.lineLimit(2)
@@ -856,13 +851,11 @@ struct OnboardingView: View {
private func whatsappPage() -> some View {
self.onboardingPage {
Text("Link WhatsApp or Telegram")
Text("Connect WhatsApp or Telegram")
.font(.largeTitle.weight(.semibold))
Text(
"""
WhatsApp uses a QR login for your personal account. Telegram uses a bot token.
Either (or both) is fine; configure them where the gateway runs.
""")
"Optional: WhatsApp uses a QR login for your personal account. Telegram uses a bot token. " +
"Configure them on the machine where the gateway runs.")
.font(.body)
.foregroundStyle(.secondary)
.multilineTextAlignment(.center)
@@ -872,7 +865,7 @@ struct OnboardingView: View {
self.onboardingCard {
self.featureRow(
title: "Open a terminal",
subtitle: "Use the same host selected above. If remote, SSH in first.",
subtitle: "Use the machine where the gateway runs. If remote, SSH in first.",
systemImage: "terminal")
Text("WhatsApp")
@@ -881,7 +874,7 @@ struct OnboardingView: View {
title: "Run `clawdis login --verbose`",
subtitle: """
Scan the QR code with WhatsApp on your phone.
We only use your personal session; no cloud gateway involved.
This links your personal session; no cloud gateway involved.
""",
systemImage: "qrcode.viewfinder")
self.featureRow(
@@ -900,7 +893,7 @@ struct OnboardingView: View {
self.featureRow(
title: "Set `TELEGRAM_BOT_TOKEN`",
subtitle: """
Create a bot with @BotFather and set the token as an env var
Create a bot with @BotFather and set the token as an env var,
(or `telegram.botToken` in `~/.clawdis/clawdis.json`).
""",
systemImage: "key")
@@ -917,13 +910,21 @@ struct OnboardingView: View {
Text("All set")
.font(.largeTitle.weight(.semibold))
self.onboardingCard {
if self.state.connectionMode == .remote {
self.featureRow(
title: "Remote gateway checklist",
subtitle: """
On your gateway host: install/update the `clawdis` package and make sure Pi has credentials
(typically `~/.pi/agent/oauth.json`). Then connect again if needed.
""",
systemImage: "network")
Divider()
.padding(.vertical, 6)
}
self.featureRow(
title: "Run the dashboard",
subtitle: """
Use the CLI helper from your scripts, and reopen onboarding from Settings
if you add a new user.
""",
systemImage: "checkmark.seal")
title: "Open the menu bar panel",
subtitle: "Click the Clawdis menu bar icon for quick chat and status.",
systemImage: "bubble.left.and.bubble.right")
self.featureRow(
title: "Try Voice Wake",
subtitle: "Enable Voice Wake in Settings for hands-free commands with a live transcript overlay.",