@clawpump/claw-agent 0.1.8 → 0.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/agent/.mailmap +4 -0
  2. package/agent/apps/desktop/README.md +3 -3
  3. package/agent/apps/desktop/assets/icon.icns +0 -0
  4. package/agent/apps/desktop/assets/icon.ico +0 -0
  5. package/agent/apps/desktop/assets/icon.png +0 -0
  6. package/agent/apps/desktop/electron/backend-ready.cjs +2 -2
  7. package/agent/apps/desktop/electron/dashboard-token.cjs +3 -3
  8. package/agent/apps/desktop/electron/hardening.cjs +1 -1
  9. package/agent/apps/desktop/electron/main.cjs +67 -67
  10. package/agent/apps/desktop/index.html +1 -1
  11. package/agent/apps/desktop/package.json +16 -16
  12. package/agent/apps/desktop/public/apple-touch-icon.png +0 -0
  13. package/agent/apps/desktop/public/claw-mark.png +0 -0
  14. package/agent/apps/desktop/scripts/after-pack.cjs +1 -1
  15. package/agent/apps/desktop/scripts/set-exe-identity.cjs +2 -2
  16. package/agent/apps/desktop/scripts/test-desktop.mjs +3 -3
  17. package/agent/apps/desktop/src/app/chat/composer/controls.tsx +2 -0
  18. package/agent/apps/desktop/src/app/chat/composer/index.tsx +10 -0
  19. package/agent/apps/desktop/src/app/chat/composer/pod-credits.tsx +49 -0
  20. package/agent/apps/desktop/src/app/chat/index.tsx +1 -1
  21. package/agent/apps/desktop/src/app/chat/sidebar/index.tsx +4 -2
  22. package/agent/apps/desktop/src/app/desktop-controller.tsx +18 -0
  23. package/agent/apps/desktop/src/app/gateway/hooks/use-gateway-request.ts +1 -1
  24. package/agent/apps/desktop/src/app/messaging/index.tsx +5 -5
  25. package/agent/apps/desktop/src/app/routes.ts +9 -1
  26. package/agent/apps/desktop/src/app/session/hooks/use-message-stream.ts +3 -3
  27. package/agent/apps/desktop/src/app/settings/constants.ts +5 -5
  28. package/agent/apps/desktop/src/app/settings/model-settings.tsx +1 -1
  29. package/agent/apps/desktop/src/app/settings/providers-settings.tsx +46 -1
  30. package/agent/apps/desktop/src/app/settings/uninstall-section.tsx +5 -5
  31. package/agent/apps/desktop/src/app/types.ts +9 -1
  32. package/agent/apps/desktop/src/app/wallet/index.tsx +244 -0
  33. package/agent/apps/desktop/src/app/x402/index.tsx +162 -0
  34. package/agent/apps/desktop/src/components/assistant-ui/thread.tsx +1 -1
  35. package/agent/apps/desktop/src/components/brand-mark.tsx +2 -2
  36. package/agent/apps/desktop/src/components/chat/intro-copy.jsonl +6 -6
  37. package/agent/apps/desktop/src/components/chat/intro.tsx +4 -4
  38. package/agent/apps/desktop/src/components/model-picker.tsx +64 -4
  39. package/agent/apps/desktop/src/components/pod-setup-dialog.tsx +227 -0
  40. package/agent/apps/desktop/src/hermes.ts +109 -3
  41. package/agent/apps/desktop/src/i18n/en.ts +80 -78
  42. package/agent/apps/desktop/src/i18n/ja.ts +82 -82
  43. package/agent/apps/desktop/src/i18n/runtime.test.ts +2 -2
  44. package/agent/apps/desktop/src/i18n/zh-hant.ts +82 -82
  45. package/agent/apps/desktop/src/i18n/zh.ts +87 -87
  46. package/agent/apps/desktop/src/lib/desktop-fs.ts +1 -1
  47. package/agent/apps/desktop/src/lib/desktop-slash-commands.ts +4 -4
  48. package/agent/apps/desktop/src/store/composer.ts +7 -0
  49. package/agent/apps/desktop/src/store/onboarding.ts +5 -5
  50. package/agent/apps/desktop/src/themes/presets.ts +54 -54
  51. package/agent/cli.py +184 -10
  52. package/agent/hermes_cli/distribution.py +188 -8
  53. package/agent/hermes_cli/gui_uninstall.py +11 -6
  54. package/agent/hermes_cli/main.py +9 -4
  55. package/agent/hermes_cli/providers.py +29 -0
  56. package/agent/hermes_cli/web_server.py +180 -2
  57. package/agent/plugins/model-providers/usepod/__init__.py +7 -1
  58. package/agent/scripts/install.sh +3 -1
  59. package/agent/scripts/release.py +1 -0
  60. package/agent/web/src/components/ChatSidebar.tsx +5 -0
  61. package/agent/web/src/components/ModelPickerDialog.tsx +28 -1
  62. package/agent/web/src/components/PodCredits.tsx +57 -0
  63. package/agent/web/src/components/PodSetupDialog.tsx +240 -0
  64. package/agent/web/src/lib/api.ts +23 -0
  65. package/package.json +1 -1
package/agent/.mailmap CHANGED
@@ -14,6 +14,10 @@
14
14
  Teknium <127238744+teknium1@users.noreply.github.com> <teknium1@gmail.com>
15
15
  Teknium <127238744+teknium1@users.noreply.github.com> <teknium@nousresearch.com>
16
16
 
17
+ # === Tomas Oliver — ClawPump maintainer (multiple emails) ===
18
+ Tomas Oliver <tomi204@users.noreply.github.com> <0xtomi204@gmail.com>
19
+ Tomas Oliver <tomi204@users.noreply.github.com> <tomi204@outlook.com>
20
+
17
21
  # === Contributors — personal/work emails mapped to GitHub noreply ===
18
22
  # Format: Canonical Name <GH-noreply> <commit-email>
19
23
 
@@ -1,4 +1,4 @@
1
- # Hermes Desktop
1
+ # Claw Agent — Desktop 🦀
2
2
 
3
3
  <p align="center">
4
4
  <a href="https://github.com/NousResearch/hermes-agent/releases"><img src="https://img.shields.io/badge/Download-macOS%20%C2%B7%20Windows%20%C2%B7%20Linux-FFD700?style=for-the-badge" alt="Download"></a>
@@ -7,7 +7,7 @@
7
7
  <a href="https://github.com/NousResearch/hermes-agent/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-MIT-green?style=for-the-badge" alt="License: MIT"></a>
8
8
  </p>
9
9
 
10
- **The native desktop app for [Hermes Agent](../../README.md) the self-improving AI agent from [Nous Research](https://nousresearch.com).** Same agent, same skills, same memory as the CLI and gateway, in a polished native window — chat with streaming tool output, side-by-side previews, a file browser, voice, and settings, no terminal required. Available for **macOS, Windows, and Linux**.
10
+ **Claw Agent by ClawPump — the native desktop app for Solana agents, built on [Hermes Agent](../../README.md) by [Nous Research](https://nousresearch.com).** Same agent, same skills, same memory as the CLI and gateway, in a polished native window — chat with streaming tool output, side-by-side previews, a file browser, voice, and settings, no terminal required. Available for **macOS, Windows, and Linux**.
11
11
 
12
12
  <table>
13
13
  <tr><td><b>Chat with the full agent</b></td><td>Streaming responses, live tool activity, structured tool summaries, and the same conversation history as every other Hermes surface.</td></tr>
@@ -138,4 +138,4 @@ Remove-Item -Recurse -Force "$env:LOCALAPPDATA\hermes\hermes-agent\venv"
138
138
 
139
139
  MIT — see [LICENSE](../../LICENSE).
140
140
 
141
- Built by [Nous Research](https://nousresearch.com).
141
+ Built on Hermes by [Nous Research](https://nousresearch.com). ClawPump distribution.
Binary file
Binary file
Binary file
@@ -44,7 +44,7 @@ function waitForDashboardPort(child, timeoutMs = 45_000) {
44
44
 
45
45
  function onExit(code, signal) {
46
46
  cleanup()
47
- reject(new Error(`Hermes backend: exited before port announcement (${signal || code})`))
47
+ reject(new Error(`Claw Agent backend: exited before port announcement (${signal || code})`))
48
48
  }
49
49
 
50
50
  function onError(err) {
@@ -54,7 +54,7 @@ function waitForDashboardPort(child, timeoutMs = 45_000) {
54
54
 
55
55
  const timer = setTimeout(() => {
56
56
  cleanup()
57
- reject(new Error(`Timed out waiting for Hermes backend port announcement (${timeoutMs}ms)`))
57
+ reject(new Error(`Timed out waiting for Claw Agent backend port announcement (${timeoutMs}ms)`))
58
58
  }, timeoutMs)
59
59
 
60
60
  child.stdout.on('data', onData)
@@ -12,13 +12,13 @@ const DEFAULT_TOKEN_FETCH_TIMEOUT_MS = 3_000
12
12
  async function fetchPublicText(url, options = {}) {
13
13
  const { protocol } = new URL(url)
14
14
  if (protocol !== 'http:' && protocol !== 'https:') {
15
- throw new Error(`Unsupported Hermes backend URL protocol: ${protocol}`)
15
+ throw new Error(`Unsupported Claw Agent backend URL protocol: ${protocol}`)
16
16
  }
17
17
 
18
18
  const timeoutMs = options.timeoutMs ?? DEFAULT_TOKEN_FETCH_TIMEOUT_MS
19
19
  const res = await fetch(url, { signal: AbortSignal.timeout(timeoutMs) }).catch(error => {
20
20
  if (error.name === 'TimeoutError') {
21
- throw new Error(`Timed out connecting to Hermes backend after ${timeoutMs}ms`)
21
+ throw new Error(`Timed out connecting to Claw Agent backend after ${timeoutMs}ms`)
22
22
  }
23
23
  throw error
24
24
  })
@@ -73,7 +73,7 @@ function isForeignBackendToken({ servedToken, spawnToken, childAlive }) {
73
73
  * failing loudly on a foreign backend. `childAlive` is a thunk so liveness is
74
74
  * sampled after the fetch, not before.
75
75
  */
76
- async function adoptServedDashboardToken(baseUrl, spawnToken, { childAlive, label = 'Hermes backend', ...options }) {
76
+ async function adoptServedDashboardToken(baseUrl, spawnToken, { childAlive, label = 'Claw Agent backend', ...options }) {
77
77
  const servedToken = await resolveServedDashboardToken(baseUrl, spawnToken, options).catch(error => {
78
78
  options.rememberLog?.(`[boot] could not read served dashboard token (${label}): ${error.message}`)
79
79
  return spawnToken
@@ -39,7 +39,7 @@ function encryptDesktopSecret(value, safeStorageApi) {
39
39
 
40
40
  if (!encryptionAvailable) {
41
41
  throw new Error(
42
- 'Secure token storage is unavailable, so Hermes Desktop cannot save remote gateway tokens. ' +
42
+ 'Secure token storage is unavailable, so Claw Agent Desktop cannot save remote gateway tokens. ' +
43
43
  'Set HERMES_DESKTOP_REMOTE_URL and HERMES_DESKTOP_REMOTE_TOKEN in your environment, or enable OS keychain access and try again.'
44
44
  )
45
45
  }
@@ -268,7 +268,7 @@ function resolveHermesHome() {
268
268
  }
269
269
 
270
270
  const HERMES_HOME = resolveHermesHome()
271
- // ACTIVE_HERMES_ROOT — the canonical mutable Hermes install. Same path
271
+ // ACTIVE_HERMES_ROOT — the canonical mutable Claw Agent install. Same path
272
272
  // install.ps1 / install.sh use, so a desktop-only user and a CLI-only user end
273
273
  // up with identical layouts and can share one install.
274
274
  const ACTIVE_HERMES_ROOT = path.join(HERMES_HOME, 'hermes-agent')
@@ -335,7 +335,7 @@ const BOOT_FAKE_STEP_MS = (() => {
335
335
  if (!Number.isFinite(raw) || raw <= 0) return 650
336
336
  return Math.max(120, raw)
337
337
  })()
338
- const APP_NAME = 'Hermes'
338
+ const APP_NAME = 'Claw Agent'
339
339
  const TITLEBAR_HEIGHT = 34
340
340
  const MACOS_TRAFFIC_LIGHTS_HEIGHT = 14
341
341
  const WINDOW_BUTTON_POSITION = {
@@ -597,7 +597,7 @@ app.setName(APP_NAME)
597
597
  app.setAboutPanelOptions({
598
598
  applicationName: APP_NAME,
599
599
  applicationVersion: resolveHermesVersion(),
600
- copyright: 'Copyright © 2026 Nous Research'
600
+ copyright: 'Copyright © 2026 Nous Research · ClawPump distribution'
601
601
  })
602
602
 
603
603
  // Custom scheme for streaming local media (video/audio) into the renderer.
@@ -709,7 +709,7 @@ let nativeThemeListenerInstalled = false
709
709
  let bootProgressState = {
710
710
  error: null,
711
711
  fakeMode: BOOT_FAKE_MODE,
712
- message: 'Waiting to start Hermes backend',
712
+ message: 'Waiting to start Claw Agent backend',
713
713
  phase: 'idle',
714
714
  progress: 0,
715
715
  running: false,
@@ -1801,7 +1801,7 @@ async function applyUpdates(opts = {}) {
1801
1801
  return { ok: true, manual: true, command, hermesRoot: updateRoot }
1802
1802
  }
1803
1803
 
1804
- emitUpdateProgress({ stage: 'restart', message: 'Handing off to the Hermes updater…', percent: 100 })
1804
+ emitUpdateProgress({ stage: 'restart', message: 'Handing off to the Claw Agent updater…', percent: 100 })
1805
1805
  repairMacUpdaterHelper(updater)
1806
1806
 
1807
1807
  const updateRoot = resolveUpdateRoot()
@@ -1998,7 +1998,7 @@ async function applyUpdatesPosixInApp() {
1998
1998
  // best effort
1999
1999
  }
2000
2000
 
2001
- emitUpdateProgress({ stage: 'update', message: 'Updating Hermes (git + dependencies)…', percent: 10 })
2001
+ emitUpdateProgress({ stage: 'update', message: 'Updating Claw Agent (git + dependencies)…', percent: 10 })
2002
2002
  const updated = await runStreamedUpdate(hermes, ['update', '--yes', ...branchArgs], {
2003
2003
  cwd: updateRoot,
2004
2004
  env,
@@ -2022,15 +2022,15 @@ async function applyUpdatesPosixInApp() {
2022
2022
  if (rebuilt.code !== 0) {
2023
2023
  emitUpdateProgress({
2024
2024
  stage: 'error',
2025
- message: 'Backend updated, but the desktop rebuild failed. Restart Hermes to retry.',
2025
+ message: `Backend updated, but the desktop rebuild failed. Restart ${APP_NAME} to retry.`,
2026
2026
  error: rebuilt.error || 'rebuild-failed'
2027
2027
  })
2028
2028
  return { ok: false, backendUpdated: true, error: 'desktop rebuild failed' }
2029
2029
  }
2030
2030
 
2031
2031
  const rebuiltApp = [
2032
- path.join(updateRoot, 'apps', 'desktop', 'release', 'mac-arm64', 'Hermes.app'),
2033
- path.join(updateRoot, 'apps', 'desktop', 'release', 'mac', 'Hermes.app')
2032
+ path.join(updateRoot, 'apps', 'desktop', 'release', 'mac-arm64', 'Claw Agent.app'),
2033
+ path.join(updateRoot, 'apps', 'desktop', 'release', 'mac', 'Claw Agent.app')
2034
2034
  ].find(directoryExists)
2035
2035
  const targetApp = runningAppBundle()
2036
2036
 
@@ -2039,7 +2039,7 @@ async function applyUpdatesPosixInApp() {
2039
2039
  if (!rebuiltApp || !targetApp) {
2040
2040
  emitUpdateProgress({
2041
2041
  stage: 'done',
2042
- message: 'Backend updated. Restart Hermes to load the new version.',
2042
+ message: `Backend updated. Restart ${APP_NAME} to load the new version.`,
2043
2043
  percent: 100
2044
2044
  })
2045
2045
  return { ok: true, backendUpdated: true, rebuiltApp: rebuiltApp || null }
@@ -2075,7 +2075,7 @@ fi
2075
2075
  } catch (err) {
2076
2076
  emitUpdateProgress({
2077
2077
  stage: 'done',
2078
- message: 'Backend + app updated. Restart Hermes to load the new version.',
2078
+ message: `Backend + app updated. Restart ${APP_NAME} to load the new version.`,
2079
2079
  percent: 100
2080
2080
  })
2081
2081
  rememberLog(`[updates] could not write swap script: ${err.message}; rebuilt app at ${rebuiltApp}`)
@@ -2339,7 +2339,7 @@ function resolveHermesBackend(dashboardArgs) {
2339
2339
  // checkout. Honour it as-is (no bootstrap; the user is driving).
2340
2340
  const overrideRoot = process.env.HERMES_DESKTOP_HERMES_ROOT && path.resolve(process.env.HERMES_DESKTOP_HERMES_ROOT)
2341
2341
  if (overrideRoot && isHermesSourceRoot(overrideRoot)) {
2342
- const backend = createPythonBackend(overrideRoot, `Hermes source at ${overrideRoot}`, dashboardArgs)
2342
+ const backend = createPythonBackend(overrideRoot, `Claw Agent source at ${overrideRoot}`, dashboardArgs)
2343
2343
  if (backend) return backend
2344
2344
  }
2345
2345
 
@@ -2348,7 +2348,7 @@ function resolveHermesBackend(dashboardArgs) {
2348
2348
  // installed `hermes` on PATH so local Python edits are actually exercised.
2349
2349
  // (In dev with no checkout, SOURCE_REPO_ROOT won't pass isHermesSourceRoot.)
2350
2350
  if (!IS_PACKAGED && isHermesSourceRoot(SOURCE_REPO_ROOT)) {
2351
- const backend = createPythonBackend(SOURCE_REPO_ROOT, `Hermes source at ${SOURCE_REPO_ROOT}`, dashboardArgs)
2351
+ const backend = createPythonBackend(SOURCE_REPO_ROOT, `Claw Agent source at ${SOURCE_REPO_ROOT}`, dashboardArgs)
2352
2352
  if (backend) return backend
2353
2353
  }
2354
2354
 
@@ -2386,7 +2386,7 @@ function resolveHermesBackend(dashboardArgs) {
2386
2386
 
2387
2387
  if (hermesCommand) {
2388
2388
  if (looksLikeDesktopAppBinary(hermesCommand)) {
2389
- rememberLog(`Ignoring desktop app executable on PATH while resolving Hermes CLI: ${hermesCommand}`)
2389
+ rememberLog(`Ignoring desktop app executable on PATH while resolving Claw Agent CLI: ${hermesCommand}`)
2390
2390
  hermesCommand = null
2391
2391
  }
2392
2392
  }
@@ -2402,7 +2402,7 @@ function resolveHermesBackend(dashboardArgs) {
2402
2402
  const shellForProbe = isCommandScript(hermesCommand)
2403
2403
  if (verifyHermesCli(hermesCommand, { shell: shellForProbe })) {
2404
2404
  return {
2405
- label: `existing Hermes CLI at ${hermesCommand}`,
2405
+ label: `existing Claw Agent CLI at ${hermesCommand}`,
2406
2406
  command: hermesCommand,
2407
2407
  args: dashboardArgs,
2408
2408
  bootstrap: false,
@@ -2412,7 +2412,7 @@ function resolveHermesBackend(dashboardArgs) {
2412
2412
  }
2413
2413
  }
2414
2414
  rememberLog(
2415
- `Ignoring existing Hermes CLI at ${hermesCommand}: --version probe failed; falling through to bootstrap.`
2415
+ `Ignoring existing Claw Agent CLI at ${hermesCommand}: --version probe failed; falling through to bootstrap.`
2416
2416
  )
2417
2417
  }
2418
2418
  }
@@ -2456,7 +2456,7 @@ function resolveHermesBackend(dashboardArgs) {
2456
2456
  // is a recoverable state the GUI can drive through.
2457
2457
  return {
2458
2458
  kind: 'bootstrap-needed',
2459
- label: 'Hermes Agent not installed yet; bootstrap required',
2459
+ label: 'Claw Agent not installed yet; bootstrap required',
2460
2460
  command: null,
2461
2461
  args: dashboardArgs,
2462
2462
  bootstrap: true,
@@ -2486,10 +2486,10 @@ async function ensureRuntime(backend) {
2486
2486
  // will rewire startup to spawn the window first and route bootstrap events
2487
2487
  // to a renderer-side install overlay.
2488
2488
  if (backend.kind === 'bootstrap-needed') {
2489
- rememberLog('[bootstrap] no Hermes install found; starting first-launch bootstrap')
2489
+ rememberLog('[bootstrap] no Claw Agent install found; starting first-launch bootstrap')
2490
2490
 
2491
2491
  if (await handOffWindowsBootstrapRecovery('bootstrap-needed')) {
2492
- const handoffError = new Error('Hermes recovery was handed off to Hermes Setup. The desktop will restart when recovery completes.')
2492
+ const handoffError = new Error('Claw Agent recovery was handed off to Claw Agent Setup. The desktop will restart when recovery completes.')
2493
2493
  handoffError.isBootstrapFailure = true
2494
2494
  handoffError.bootstrapHandedOff = true
2495
2495
  bootstrapFailure = handoffError
@@ -2543,7 +2543,7 @@ async function ensureRuntime(backend) {
2543
2543
  bootstrapAbortController = null
2544
2544
 
2545
2545
  if (bootstrapResult.cancelled) {
2546
- const cancelledError = new Error('Hermes install was cancelled.')
2546
+ const cancelledError = new Error('Claw Agent install was cancelled.')
2547
2547
  cancelledError.isBootstrapFailure = true
2548
2548
  cancelledError.bootstrapCancelled = true
2549
2549
  bootstrapFailure = cancelledError
@@ -2552,7 +2552,7 @@ async function ensureRuntime(backend) {
2552
2552
 
2553
2553
  if (!bootstrapResult.ok) {
2554
2554
  const bootstrapError = new Error(
2555
- `Hermes bootstrap failed${bootstrapResult.failedStage ? ` at stage '${bootstrapResult.failedStage}'` : ''}: ` +
2555
+ `Claw Agent bootstrap failed${bootstrapResult.failedStage ? ` at stage '${bootstrapResult.failedStage}'` : ''}: ` +
2556
2556
  `${bootstrapResult.error || 'unknown error'}. ` +
2557
2557
  `Check ${path.join(HERMES_HOME, 'logs', 'desktop.log')} for the full transcript.`
2558
2558
  )
@@ -2579,7 +2579,7 @@ async function ensureRuntime(backend) {
2579
2579
  // attests they ran successfully).
2580
2580
  if (!isHermesSourceRoot(ACTIVE_HERMES_ROOT)) {
2581
2581
  throw new Error(
2582
- `Hermes install at ${ACTIVE_HERMES_ROOT} is missing or incomplete. ` +
2582
+ `Claw Agent install at ${ACTIVE_HERMES_ROOT} is missing or incomplete. ` +
2583
2583
  'Reinstall via the desktop installer or scripts/install.ps1.'
2584
2584
  )
2585
2585
  }
@@ -2592,10 +2592,10 @@ async function ensureRuntime(backend) {
2592
2592
  // here via an external `hermes` on PATH, this check still helps.
2593
2593
  if (IS_WINDOWS && !findGitBash()) {
2594
2594
  throw new Error(
2595
- 'Git for Windows is required for Hermes on Windows (provides Git Bash, ' +
2595
+ 'Git for Windows is required for Claw Agent on Windows (provides Git Bash, ' +
2596
2596
  "which the agent's terminal tool uses). Install it from " +
2597
2597
  'https://git-scm.com/download/win or run `winget install -e --id Git.Git`, ' +
2598
- 'then relaunch Hermes.'
2598
+ 'then relaunch Claw Agent.'
2599
2599
  )
2600
2600
  }
2601
2601
 
@@ -2609,7 +2609,7 @@ async function ensureRuntime(backend) {
2609
2609
  // install.ps1 succeeds. If we hit this, the user (or a deleted venv)
2610
2610
  // broke the invariant; tell them to re-run the install.
2611
2611
  throw new Error(
2612
- `Hermes venv missing at ${VENV_ROOT}. Re-run the desktop installer or ` + '`scripts/install.ps1` to rebuild it.'
2612
+ `Claw Agent venv missing at ${VENV_ROOT}. Re-run the desktop installer or ` + '`scripts/install.ps1` to rebuild it.'
2613
2613
  )
2614
2614
  }
2615
2615
 
@@ -2617,7 +2617,7 @@ async function ensureRuntime(backend) {
2617
2617
  backend.label = `Hermes at ${ACTIVE_HERMES_ROOT} (venv: ${VENV_ROOT})`
2618
2618
  updateBootProgress({
2619
2619
  phase: 'runtime.ready',
2620
- message: 'Hermes runtime is ready',
2620
+ message: 'Claw Agent runtime is ready',
2621
2621
  progress: 82,
2622
2622
  running: true,
2623
2623
  error: null
@@ -2634,7 +2634,7 @@ function fetchJson(url, token, options = {}) {
2634
2634
  const timeoutMs = resolveTimeoutMs(options.timeoutMs, DEFAULT_FETCH_TIMEOUT_MS)
2635
2635
 
2636
2636
  if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
2637
- reject(new Error(`Unsupported Hermes backend URL protocol: ${parsed.protocol}`))
2637
+ reject(new Error(`Unsupported Claw Agent backend URL protocol: ${parsed.protocol}`))
2638
2638
  return
2639
2639
  }
2640
2640
 
@@ -2672,7 +2672,7 @@ function fetchJson(url, token, options = {}) {
2672
2672
  reject(
2673
2673
  new Error(
2674
2674
  `Expected JSON from ${url} but got HTML (status ${res.statusCode}). ` +
2675
- 'The endpoint is likely missing on the Hermes backend.'
2675
+ 'The endpoint is likely missing on the Claw Agent backend.'
2676
2676
  )
2677
2677
  )
2678
2678
  return
@@ -2688,7 +2688,7 @@ function fetchJson(url, token, options = {}) {
2688
2688
 
2689
2689
  req.on('error', reject)
2690
2690
  req.setTimeout(timeoutMs, () => {
2691
- req.destroy(new Error(`Timed out connecting to Hermes backend after ${timeoutMs}ms`))
2691
+ req.destroy(new Error(`Timed out connecting to Claw Agent backend after ${timeoutMs}ms`))
2692
2692
  })
2693
2693
  if (body) req.write(body)
2694
2694
  req.end()
@@ -2714,7 +2714,7 @@ function fetchPublicJson(url, options = {}) {
2714
2714
  const timeoutMs = resolveTimeoutMs(options.timeoutMs, DEFAULT_FETCH_TIMEOUT_MS)
2715
2715
 
2716
2716
  if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
2717
- reject(new Error(`Unsupported Hermes backend URL protocol: ${parsed.protocol}`))
2717
+ reject(new Error(`Unsupported Claw Agent backend URL protocol: ${parsed.protocol}`))
2718
2718
  return
2719
2719
  }
2720
2720
 
@@ -2746,7 +2746,7 @@ function fetchPublicJson(url, options = {}) {
2746
2746
  reject(
2747
2747
  new Error(
2748
2748
  `Expected JSON from ${url} but got HTML (status ${res.statusCode}). ` +
2749
- 'The endpoint is likely missing on the Hermes backend.'
2749
+ 'The endpoint is likely missing on the Claw Agent backend.'
2750
2750
  )
2751
2751
  )
2752
2752
  return
@@ -2762,7 +2762,7 @@ function fetchPublicJson(url, options = {}) {
2762
2762
 
2763
2763
  req.on('error', reject)
2764
2764
  req.setTimeout(timeoutMs, () => {
2765
- req.destroy(new Error(`Timed out connecting to Hermes backend after ${timeoutMs}ms`))
2765
+ req.destroy(new Error(`Timed out connecting to Claw Agent backend after ${timeoutMs}ms`))
2766
2766
  })
2767
2767
  if (body) req.write(body)
2768
2768
  req.end()
@@ -3288,7 +3288,7 @@ async function waitForHermes(baseUrl, token) {
3288
3288
  }
3289
3289
  }
3290
3290
 
3291
- throw new Error(`Hermes backend did not become ready: ${lastError?.message || 'timeout'}`)
3291
+ throw new Error(`Claw Agent backend did not become ready: ${lastError?.message || 'timeout'}`)
3292
3292
  }
3293
3293
 
3294
3294
  function getWindowButtonPosition() {
@@ -3734,7 +3734,7 @@ function installMediaPermissions() {
3734
3734
  // ---------------------------------------------------------------------------
3735
3735
  // OAuth remote-gateway auth.
3736
3736
  //
3737
- // Hosted Hermes gateways gate the dashboard behind an OAuth provider (e.g.
3737
+ // Hosted Claw Agent gateways gate the dashboard behind an OAuth provider (e.g.
3738
3738
  // Nous Research) instead of a static session token. The auth model is
3739
3739
  // fundamentally different from the token path:
3740
3740
  //
@@ -3875,7 +3875,7 @@ function openOauthLoginWindow(baseUrl) {
3875
3875
  win = new BrowserWindow({
3876
3876
  width: 520,
3877
3877
  height: 720,
3878
- title: 'Sign in to Hermes gateway',
3878
+ title: 'Sign in to Claw Agent gateway',
3879
3879
  autoHideMenuBar: true,
3880
3880
  webPreferences: {
3881
3881
  contextIsolation: true,
@@ -3930,7 +3930,7 @@ function fetchJsonViaOauthSession(url, options = {}) {
3930
3930
  return
3931
3931
  }
3932
3932
  if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
3933
- reject(new Error(`Unsupported Hermes backend URL protocol: ${parsed.protocol}`))
3933
+ reject(new Error(`Unsupported Claw Agent backend URL protocol: ${parsed.protocol}`))
3934
3934
  return
3935
3935
  }
3936
3936
  const body = serializeJsonBody(options.body)
@@ -3953,7 +3953,7 @@ function fetchJsonViaOauthSession(url, options = {}) {
3953
3953
  } catch {
3954
3954
  // already finished
3955
3955
  }
3956
- reject(new Error(`Timed out connecting to Hermes backend after ${timeoutMs}ms`))
3956
+ reject(new Error(`Timed out connecting to Claw Agent backend after ${timeoutMs}ms`))
3957
3957
  }, timeoutMs)
3958
3958
 
3959
3959
  request.on('response', res => {
@@ -4288,7 +4288,7 @@ async function buildRemoteConnection(rawUrl, authMode, token, source) {
4288
4288
  // the authoritative liveness check.
4289
4289
  if (!(await hasLiveOauthSession(baseUrl))) {
4290
4290
  const err = new Error(
4291
- 'Remote Hermes gateway uses OAuth, but you are not signed in. ' +
4291
+ 'Remote Claw Agent gateway uses OAuth, but you are not signed in. ' +
4292
4292
  'Open Settings → Gateway and click "Sign in", or switch back to Local.'
4293
4293
  )
4294
4294
  err.needsOauthLogin = true
@@ -4320,7 +4320,7 @@ async function buildRemoteConnection(rawUrl, authMode, token, source) {
4320
4320
 
4321
4321
  if (!token) {
4322
4322
  throw new Error(
4323
- 'Remote Hermes gateway is selected, but no session token is saved. ' +
4323
+ 'Remote Claw Agent gateway is selected, but no session token is saved. ' +
4324
4324
  'Open Settings → Gateway and save a token, or switch back to Local.'
4325
4325
  )
4326
4326
  }
@@ -4361,7 +4361,7 @@ async function resolveRemoteBackend(profile) {
4361
4361
  if (!rawEnvToken) {
4362
4362
  throw new Error(
4363
4363
  'HERMES_DESKTOP_REMOTE_URL is set but HERMES_DESKTOP_REMOTE_TOKEN is not. ' +
4364
- 'Both must be provided to connect to a remote Hermes backend.'
4364
+ 'Both must be provided to connect to a remote Claw Agent backend.'
4365
4365
  )
4366
4366
  }
4367
4367
  return buildRemoteConnection(rawEnvUrl, 'token', rawEnvToken, 'env')
@@ -4511,7 +4511,7 @@ async function testDesktopConnectionConfig(input = {}) {
4511
4511
  // connects — a separate transport with separate server-side guards (Host/
4512
4512
  // Origin, ws-ticket/token auth). Validating only the HTTP side produced a
4513
4513
  // false-positive "reachable" while the real boot still failed with "Could not
4514
- // connect to Hermes gateway". Mirror the renderer's connect here so the test
4514
+ // connect to Claw Agent gateway". Mirror the renderer's connect here so the test
4515
4515
  // reflects the full path the app actually uses.
4516
4516
  const wsUrl = await resolveTestWsUrl(baseUrl, authMode, token, { mintTicket: mintGatewayWsTicket })
4517
4517
  // Skip the WS leg only when the runtime genuinely lacks a WebSocket (so an
@@ -4711,7 +4711,7 @@ async function spawnPoolBackend(profile, entry) {
4711
4711
  const hermesCwd = resolveHermesCwd()
4712
4712
  const webDist = resolveWebDist()
4713
4713
 
4714
- rememberLog(`Starting Hermes backend for profile "${profile}" via ${backend.label}`)
4714
+ rememberLog(`Starting Claw Agent backend for profile "${profile}" via ${backend.label}`)
4715
4715
 
4716
4716
  const child = spawn(
4717
4717
  backend.command,
@@ -4748,16 +4748,16 @@ async function spawnPoolBackend(profile, entry) {
4748
4748
  rejectStart = reject
4749
4749
  })
4750
4750
  child.once('error', error => {
4751
- rememberLog(`Hermes backend for profile "${profile}" failed to start: ${error.message}`)
4751
+ rememberLog(`Claw Agent backend for profile "${profile}" failed to start: ${error.message}`)
4752
4752
  backendPool.delete(profile)
4753
4753
  rejectStart?.(error)
4754
4754
  })
4755
4755
  child.once('exit', (code, signal) => {
4756
- rememberLog(`Hermes backend for profile "${profile}" exited (${signal || code})`)
4756
+ rememberLog(`Claw Agent backend for profile "${profile}" exited (${signal || code})`)
4757
4757
  backendPool.delete(profile)
4758
4758
  if (!ready) {
4759
4759
  rejectStart?.(
4760
- new Error(`Hermes backend for profile "${profile}" exited before it became ready (${signal || code}).`)
4760
+ new Error(`Claw Agent backend for profile "${profile}" exited before it became ready (${signal || code}).`)
4761
4761
  )
4762
4762
  }
4763
4763
  })
@@ -4771,7 +4771,7 @@ async function spawnPoolBackend(profile, entry) {
4771
4771
  ready = true
4772
4772
  const authToken = await adoptServedDashboardToken(baseUrl, token, {
4773
4773
  childAlive: () => child.exitCode === null && !child.killed,
4774
- label: `Hermes backend for profile "${profile}"`,
4774
+ label: `Claw Agent backend for profile "${profile}"`,
4775
4775
  rememberLog
4776
4776
  })
4777
4777
  entry.token = authToken
@@ -4879,16 +4879,16 @@ async function startHermes() {
4879
4879
  if (connectionPromise) return connectionPromise
4880
4880
 
4881
4881
  connectionPromise = (async () => {
4882
- await advanceBootProgress('backend.resolve', 'Resolving Hermes backend', 8)
4882
+ await advanceBootProgress('backend.resolve', 'Resolving Claw Agent backend', 8)
4883
4883
  // Resolve for the desktop's primary profile so a per-profile remote
4884
4884
  // override on the active profile is honored (falls back to env / global).
4885
4885
  const remote = await resolveRemoteBackend(primaryProfileKey())
4886
4886
  if (remote) {
4887
- await advanceBootProgress('backend.remote', `Connecting to remote Hermes backend at ${remote.baseUrl}`, 24)
4887
+ await advanceBootProgress('backend.remote', `Connecting to remote Claw Agent backend at ${remote.baseUrl}`, 24)
4888
4888
  await waitForHermes(remote.baseUrl, remote.token)
4889
4889
  updateBootProgress({
4890
4890
  phase: 'backend.ready',
4891
- message: 'Remote Hermes backend is ready',
4891
+ message: 'Remote Claw Agent backend is ready',
4892
4892
  progress: 94,
4893
4893
  running: true,
4894
4894
  error: null
@@ -4917,13 +4917,13 @@ async function startHermes() {
4917
4917
  if (activeProfile) {
4918
4918
  dashboardArgs.unshift('--profile', activeProfile)
4919
4919
  }
4920
- await advanceBootProgress('backend.runtime', 'Resolving Hermes runtime', 28)
4920
+ await advanceBootProgress('backend.runtime', 'Resolving Claw Agent runtime', 28)
4921
4921
  const backend = await ensureRuntime(resolveHermesBackend(dashboardArgs))
4922
4922
  const hermesCwd = resolveHermesCwd()
4923
4923
  const webDist = resolveWebDist()
4924
4924
 
4925
- await advanceBootProgress('backend.spawn', `Starting Hermes backend via ${backend.label}`, 84)
4926
- rememberLog(`Starting Hermes backend via ${backend.label}`)
4925
+ await advanceBootProgress('backend.spawn', `Starting Claw Agent backend via ${backend.label}`, 84)
4926
+ rememberLog(`Starting Claw Agent backend via ${backend.label}`)
4927
4927
 
4928
4928
  hermesProcess = spawn(
4929
4929
  backend.command,
@@ -4962,11 +4962,11 @@ async function startHermes() {
4962
4962
  rejectBackendStart = reject
4963
4963
  })
4964
4964
  hermesProcess.once('error', error => {
4965
- rememberLog(`Hermes backend failed to start: ${error.message}`)
4965
+ rememberLog(`Claw Agent backend failed to start: ${error.message}`)
4966
4966
  updateBootProgress(
4967
4967
  {
4968
4968
  error: error.message,
4969
- message: `Hermes backend failed to start: ${error.message}`,
4969
+ message: `Claw Agent backend failed to start: ${error.message}`,
4970
4970
  phase: 'backend.error',
4971
4971
  running: false
4972
4972
  },
@@ -4978,12 +4978,12 @@ async function startHermes() {
4978
4978
  rejectBackendStart?.(error)
4979
4979
  })
4980
4980
  hermesProcess.once('exit', (code, signal) => {
4981
- rememberLog(`Hermes backend exited (${signal || code})`)
4981
+ rememberLog(`Claw Agent backend exited (${signal || code})`)
4982
4982
  hermesProcess = null
4983
4983
  connectionPromise = null
4984
4984
  sendBackendExit({ code, signal })
4985
4985
  if (!backendReady) {
4986
- const message = `Hermes backend exited before it became ready (${signal || code}).`
4986
+ const message = `Claw Agent backend exited before it became ready (${signal || code}).`
4987
4987
  updateBootProgress(
4988
4988
  {
4989
4989
  error: message,
@@ -4995,18 +4995,18 @@ async function startHermes() {
4995
4995
  )
4996
4996
  rejectBackendStart?.(
4997
4997
  new Error(
4998
- `Hermes backend exited before it became ready (${signal || code}). Log: ${DESKTOP_LOG_PATH}\n${recentHermesLog()}`
4998
+ `Claw Agent backend exited before it became ready (${signal || code}). Log: ${DESKTOP_LOG_PATH}\n${recentHermesLog()}`
4999
4999
  )
5000
5000
  )
5001
5001
  }
5002
5002
  })
5003
5003
 
5004
- await advanceBootProgress('backend.port', 'Waiting for Hermes backend to launch', 86)
5004
+ await advanceBootProgress('backend.port', 'Waiting for Claw Agent backend to launch', 86)
5005
5005
  // Discover the ephemeral port the child bound to
5006
5006
  const port = await Promise.race([waitForDashboardPort(hermesProcess), backendStartFailed])
5007
5007
 
5008
5008
  const baseUrl = `http://127.0.0.1:${port}`
5009
- await advanceBootProgress('backend.wait', 'Waiting for Hermes backend to become ready', 90)
5009
+ await advanceBootProgress('backend.wait', 'Waiting for Claw Agent backend to become ready', 90)
5010
5010
  await Promise.race([waitForHermes(baseUrl, token), backendStartFailed])
5011
5011
  backendReady = true
5012
5012
  const authToken = await adoptServedDashboardToken(baseUrl, token, {
@@ -5016,7 +5016,7 @@ async function startHermes() {
5016
5016
  })
5017
5017
  updateBootProgress({
5018
5018
  phase: 'backend.ready',
5019
- message: 'Hermes backend is ready. Finalizing desktop startup',
5019
+ message: 'Claw Agent backend is ready. Finalizing desktop startup',
5020
5020
  progress: 94,
5021
5021
  running: true,
5022
5022
  error: null
@@ -5097,7 +5097,7 @@ function spawnSecondaryWindow({ sessionId, watch, newSession } = {}) {
5097
5097
  height: SESSION_WINDOW_MIN_HEIGHT,
5098
5098
  minWidth: SESSION_WINDOW_MIN_WIDTH,
5099
5099
  minHeight: SESSION_WINDOW_MIN_HEIGHT,
5100
- title: 'Hermes',
5100
+ title: APP_NAME,
5101
5101
  titleBarStyle: 'hidden',
5102
5102
  titleBarOverlay: getTitleBarOverlayOptions(),
5103
5103
  trafficLightPosition: IS_MAC ? WINDOW_BUTTON_POSITION : undefined,
@@ -5161,7 +5161,7 @@ function createWindow() {
5161
5161
  height: 800,
5162
5162
  minWidth: 400,
5163
5163
  minHeight: 620,
5164
- title: 'Hermes',
5164
+ title: APP_NAME,
5165
5165
  // Frameless title bar on every platform so the renderer can paint the
5166
5166
  // "hide sidebar" button (and other left-side titlebar tools) flush with
5167
5167
  // the top edge — matching the macOS layout where the traffic lights sit
@@ -5307,7 +5307,7 @@ ipcMain.handle('hermes:connection:revalidate', async () => {
5307
5307
  // Unreachable remote: drop the stale cache so the renderer's next reconnect
5308
5308
  // tick rebuilds a fresh, reachable descriptor. resetHermesConnection only
5309
5309
  // nulls connectionPromise for a remote (no child to SIGTERM).
5310
- rememberLog('Cached remote Hermes backend failed liveness probe; dropping stale connection.')
5310
+ rememberLog('Cached remote Claw Agent backend failed liveness probe; dropping stale connection.')
5311
5311
  resetHermesConnection()
5312
5312
  return { ok: true, rebuilt: true }
5313
5313
  }
@@ -5632,7 +5632,7 @@ ipcMain.handle('hermes:notify', (_event, payload) => {
5632
5632
  // and the body click still works.
5633
5633
  const actions = Array.isArray(payload?.actions) ? payload.actions : []
5634
5634
  const notification = new Notification({
5635
- title: payload?.title || 'Hermes',
5635
+ title: payload?.title || APP_NAME,
5636
5636
  body: payload?.body || '',
5637
5637
  silent: Boolean(payload?.silent),
5638
5638
  actions: actions.map(action => ({ type: 'button', text: String(action?.text || '') }))
@@ -6043,7 +6043,7 @@ ipcMain.handle('hermes:fs:worktrees', async (_event, cwds) => worktreesForIpc(cw
6043
6043
 
6044
6044
  ipcMain.handle('hermes:terminal:start', async (event, payload = {}) => {
6045
6045
  if (!nodePty) {
6046
- throw new Error('PTY support is unavailable. Reinstall desktop dependencies and restart Hermes.')
6046
+ throw new Error('PTY support is unavailable. Reinstall desktop dependencies and restart Claw Agent.')
6047
6047
  }
6048
6048
 
6049
6049
  ensureSpawnHelperExecutable()
@@ -6165,7 +6165,7 @@ function showAboutPanelFresh() {
6165
6165
  app.setAboutPanelOptions({
6166
6166
  applicationName: APP_NAME,
6167
6167
  applicationVersion: resolveHermesVersion(),
6168
- copyright: 'Copyright © 2026 Nous Research'
6168
+ copyright: 'Copyright © 2026 Nous Research · ClawPump distribution'
6169
6169
  })
6170
6170
  app.showAboutPanel()
6171
6171
  }
@@ -6274,7 +6274,7 @@ async function runDesktopUninstall(mode) {
6274
6274
  return {
6275
6275
  ok: false,
6276
6276
  error: 'agent-missing',
6277
- message: `Can't run the uninstaller: no Hermes agent venv at ${VENV_ROOT}.`
6277
+ message: `Can't run the uninstaller: no Claw Agent venv at ${VENV_ROOT}.`
6278
6278
  }
6279
6279
  }
6280
6280
 
@@ -8,7 +8,7 @@
8
8
  <link rel="icon" type="image/png" sizes="180x180" href="/apple-touch-icon.png" />
9
9
  <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
10
10
  <link rel="shortcut icon" href="/apple-touch-icon.png" />
11
- <title>Hermes</title>
11
+ <title>Claw Agent</title>
12
12
  <script>
13
13
  // Pre-paint the themed background before the app bundle loads. Without
14
14
  // this, the first frame (which is what `ready-to-show` waits for) is the