@hybridaione/hybridclaw 0.9.4 → 0.9.6

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 (264) hide show
  1. package/CHANGELOG.md +80 -0
  2. package/README.md +42 -12
  3. package/config.example.json +19 -1
  4. package/console/dist/assets/index-BriItkGy.css +1 -0
  5. package/console/dist/assets/{index-CWsi6Xzk.js → index-CW6-V7lC.js} +7 -6
  6. package/console/dist/assets/terminal-CTA4H1Ek.js +7 -0
  7. package/console/dist/assets/terminal-TdnZ7DQy.css +1 -0
  8. package/console/dist/index.html +2 -2
  9. package/console/package.json +3 -1
  10. package/container/Dockerfile +2 -2
  11. package/container/dist/browser-tools.js +115 -24
  12. package/container/dist/browser-tools.js.map +1 -1
  13. package/container/dist/index.js +59 -11
  14. package/container/dist/index.js.map +1 -1
  15. package/container/dist/model-retry.js +3 -1
  16. package/container/dist/model-retry.js.map +1 -1
  17. package/container/dist/providers/shared.js +72 -23
  18. package/container/dist/providers/shared.js.map +1 -1
  19. package/container/dist/runtime-paths.js +32 -2
  20. package/container/dist/runtime-paths.js.map +1 -1
  21. package/container/package-lock.json +2 -2
  22. package/container/package.json +1 -1
  23. package/container/src/browser-tools.ts +127 -22
  24. package/container/src/index.ts +75 -11
  25. package/container/src/model-retry.ts +5 -1
  26. package/container/src/providers/shared.ts +101 -24
  27. package/container/src/runtime-paths.ts +30 -2
  28. package/dist/agent/agent.d.ts.map +1 -1
  29. package/dist/agent/agent.js +3 -2
  30. package/dist/agent/agent.js.map +1 -1
  31. package/dist/audit/observability-ingest.d.ts.map +1 -1
  32. package/dist/audit/observability-ingest.js +24 -2
  33. package/dist/audit/observability-ingest.js.map +1 -1
  34. package/dist/auth/codex-auth.d.ts +0 -1
  35. package/dist/auth/codex-auth.d.ts.map +1 -1
  36. package/dist/auth/codex-auth.js +2 -2
  37. package/dist/auth/codex-auth.js.map +1 -1
  38. package/dist/auth/hybridai-auth.d.ts.map +1 -1
  39. package/dist/auth/hybridai-auth.js +6 -3
  40. package/dist/auth/hybridai-auth.js.map +1 -1
  41. package/dist/browser/browser-login.d.ts.map +1 -1
  42. package/dist/browser/browser-login.js +20 -11
  43. package/dist/browser/browser-login.js.map +1 -1
  44. package/dist/channels/channel-registry.d.ts.map +1 -1
  45. package/dist/channels/channel-registry.js +5 -1
  46. package/dist/channels/channel-registry.js.map +1 -1
  47. package/dist/channels/channel.d.ts +2 -1
  48. package/dist/channels/channel.d.ts.map +1 -1
  49. package/dist/channels/channel.js +9 -0
  50. package/dist/channels/channel.js.map +1 -1
  51. package/dist/channels/imessage/backend-bluebubbles.d.ts +3 -0
  52. package/dist/channels/imessage/backend-bluebubbles.d.ts.map +1 -0
  53. package/dist/channels/imessage/backend-bluebubbles.js +330 -0
  54. package/dist/channels/imessage/backend-bluebubbles.js.map +1 -0
  55. package/dist/channels/imessage/backend-local.d.ts +3 -0
  56. package/dist/channels/imessage/backend-local.d.ts.map +1 -0
  57. package/dist/channels/imessage/backend-local.js +229 -0
  58. package/dist/channels/imessage/backend-local.js.map +1 -0
  59. package/dist/channels/imessage/backend.d.ts +21 -0
  60. package/dist/channels/imessage/backend.d.ts.map +1 -0
  61. package/dist/channels/imessage/backend.js +2 -0
  62. package/dist/channels/imessage/backend.js.map +1 -0
  63. package/dist/channels/imessage/debounce.d.ts +15 -0
  64. package/dist/channels/imessage/debounce.d.ts.map +1 -0
  65. package/dist/channels/imessage/debounce.js +69 -0
  66. package/dist/channels/imessage/debounce.js.map +1 -0
  67. package/dist/channels/imessage/delivery.d.ts +2 -0
  68. package/dist/channels/imessage/delivery.d.ts.map +1 -0
  69. package/dist/channels/imessage/delivery.js +12 -0
  70. package/dist/channels/imessage/delivery.js.map +1 -0
  71. package/dist/channels/imessage/handle.d.ts +7 -0
  72. package/dist/channels/imessage/handle.d.ts.map +1 -0
  73. package/dist/channels/imessage/handle.js +71 -0
  74. package/dist/channels/imessage/handle.js.map +1 -0
  75. package/dist/channels/imessage/inbound-dedupe-cache.d.ts +12 -0
  76. package/dist/channels/imessage/inbound-dedupe-cache.d.ts.map +1 -0
  77. package/dist/channels/imessage/inbound-dedupe-cache.js +37 -0
  78. package/dist/channels/imessage/inbound-dedupe-cache.js.map +1 -0
  79. package/dist/channels/imessage/inbound.d.ts +30 -0
  80. package/dist/channels/imessage/inbound.d.ts.map +1 -0
  81. package/dist/channels/imessage/inbound.js +92 -0
  82. package/dist/channels/imessage/inbound.js.map +1 -0
  83. package/dist/channels/imessage/local-prereqs.d.ts +3 -0
  84. package/dist/channels/imessage/local-prereqs.d.ts.map +1 -0
  85. package/dist/channels/imessage/local-prereqs.js +33 -0
  86. package/dist/channels/imessage/local-prereqs.js.map +1 -0
  87. package/dist/channels/imessage/prompt-adapter.d.ts +3 -0
  88. package/dist/channels/imessage/prompt-adapter.d.ts.map +1 -0
  89. package/dist/channels/imessage/prompt-adapter.js +25 -0
  90. package/dist/channels/imessage/prompt-adapter.js.map +1 -0
  91. package/dist/channels/imessage/runtime.d.ts +17 -0
  92. package/dist/channels/imessage/runtime.d.ts.map +1 -0
  93. package/dist/channels/imessage/runtime.js +163 -0
  94. package/dist/channels/imessage/runtime.js.map +1 -0
  95. package/dist/channels/imessage/self-chat-guard.d.ts +21 -0
  96. package/dist/channels/imessage/self-chat-guard.d.ts.map +1 -0
  97. package/dist/channels/imessage/self-chat-guard.js +124 -0
  98. package/dist/channels/imessage/self-chat-guard.js.map +1 -0
  99. package/dist/channels/imessage/self-echo-cache.d.ts +18 -0
  100. package/dist/channels/imessage/self-echo-cache.d.ts.map +1 -0
  101. package/dist/channels/imessage/self-echo-cache.js +79 -0
  102. package/dist/channels/imessage/self-echo-cache.js.map +1 -0
  103. package/dist/channels/imessage/text-normalization.d.ts +2 -0
  104. package/dist/channels/imessage/text-normalization.d.ts.map +1 -0
  105. package/dist/channels/imessage/text-normalization.js +9 -0
  106. package/dist/channels/imessage/text-normalization.js.map +1 -0
  107. package/dist/channels/imessage/ttl-cache.d.ts +13 -0
  108. package/dist/channels/imessage/ttl-cache.d.ts.map +1 -0
  109. package/dist/channels/imessage/ttl-cache.js +62 -0
  110. package/dist/channels/imessage/ttl-cache.js.map +1 -0
  111. package/dist/channels/imessage/types.d.ts +24 -0
  112. package/dist/channels/imessage/types.d.ts.map +1 -0
  113. package/dist/channels/imessage/types.js +2 -0
  114. package/dist/channels/imessage/types.js.map +1 -0
  115. package/dist/channels/prompt-adapters.d.ts.map +1 -1
  116. package/dist/channels/prompt-adapters.js +3 -0
  117. package/dist/channels/prompt-adapters.js.map +1 -1
  118. package/dist/channels/whatsapp/auth.js +1 -1
  119. package/dist/channels/whatsapp/auth.js.map +1 -1
  120. package/dist/cli/auth-command.d.ts.map +1 -1
  121. package/dist/cli/auth-command.js +15 -76
  122. package/dist/cli/auth-command.js.map +1 -1
  123. package/dist/cli/channels-command.d.ts.map +1 -1
  124. package/dist/cli/channels-command.js +248 -5
  125. package/dist/cli/channels-command.js.map +1 -1
  126. package/dist/cli/help.d.ts +1 -0
  127. package/dist/cli/help.d.ts.map +1 -1
  128. package/dist/cli/help.js +42 -1
  129. package/dist/cli/help.js.map +1 -1
  130. package/dist/cli/plugin-command.d.ts.map +1 -1
  131. package/dist/cli/plugin-command.js +25 -1
  132. package/dist/cli/plugin-command.js.map +1 -1
  133. package/dist/cli.d.ts.map +1 -1
  134. package/dist/cli.js +111 -7
  135. package/dist/cli.js.map +1 -1
  136. package/dist/command-registry.d.ts.map +1 -1
  137. package/dist/command-registry.js +176 -2
  138. package/dist/command-registry.js.map +1 -1
  139. package/dist/config/config.d.ts +16 -0
  140. package/dist/config/config.d.ts.map +1 -1
  141. package/dist/config/config.js +61 -12
  142. package/dist/config/config.js.map +1 -1
  143. package/dist/config/runtime-config-edit.d.ts +4 -0
  144. package/dist/config/runtime-config-edit.d.ts.map +1 -0
  145. package/dist/config/runtime-config-edit.js +54 -0
  146. package/dist/config/runtime-config-edit.js.map +1 -0
  147. package/dist/config/runtime-config.d.ts +24 -2
  148. package/dist/config/runtime-config.d.ts.map +1 -1
  149. package/dist/config/runtime-config.js +113 -12
  150. package/dist/config/runtime-config.js.map +1 -1
  151. package/dist/config/runtime-paths.d.ts +2 -0
  152. package/dist/config/runtime-paths.d.ts.map +1 -0
  153. package/dist/config/runtime-paths.js +11 -0
  154. package/dist/config/runtime-paths.js.map +1 -0
  155. package/dist/doctor/checks/config.d.ts +1 -0
  156. package/dist/doctor/checks/config.d.ts.map +1 -1
  157. package/dist/doctor/checks/config.js +56 -12
  158. package/dist/doctor/checks/config.js.map +1 -1
  159. package/dist/doctor/checks/docker.d.ts.map +1 -1
  160. package/dist/doctor/checks/docker.js +32 -13
  161. package/dist/doctor/checks/docker.js.map +1 -1
  162. package/dist/gateway/admin-terminal-protocol.d.ts +20 -0
  163. package/dist/gateway/admin-terminal-protocol.d.ts.map +1 -0
  164. package/dist/gateway/admin-terminal-protocol.js +2 -0
  165. package/dist/gateway/admin-terminal-protocol.js.map +1 -0
  166. package/dist/gateway/admin-terminal.d.ts +25 -0
  167. package/dist/gateway/admin-terminal.d.ts.map +1 -0
  168. package/dist/gateway/admin-terminal.js +407 -0
  169. package/dist/gateway/admin-terminal.js.map +1 -0
  170. package/dist/gateway/gateway-http-server.d.ts.map +1 -1
  171. package/dist/gateway/gateway-http-server.js +80 -2
  172. package/dist/gateway/gateway-http-server.js.map +1 -1
  173. package/dist/gateway/gateway-service.d.ts.map +1 -1
  174. package/dist/gateway/gateway-service.js +549 -82
  175. package/dist/gateway/gateway-service.js.map +1 -1
  176. package/dist/gateway/gateway.js +158 -0
  177. package/dist/gateway/gateway.js.map +1 -1
  178. package/dist/gateway/proactive-delivery.d.ts.map +1 -1
  179. package/dist/gateway/proactive-delivery.js +3 -0
  180. package/dist/gateway/proactive-delivery.js.map +1 -1
  181. package/dist/infra/container-runner.d.ts.map +1 -1
  182. package/dist/infra/container-runner.js +43 -2
  183. package/dist/infra/container-runner.js.map +1 -1
  184. package/dist/infra/container-setup.d.ts +12 -0
  185. package/dist/infra/container-setup.d.ts.map +1 -1
  186. package/dist/infra/container-setup.js +82 -8
  187. package/dist/infra/container-setup.js.map +1 -1
  188. package/dist/infra/host-runner.d.ts.map +1 -1
  189. package/dist/infra/host-runner.js +72 -22
  190. package/dist/infra/host-runner.js.map +1 -1
  191. package/dist/infra/host-runtime-setup.d.ts +17 -0
  192. package/dist/infra/host-runtime-setup.d.ts.map +1 -0
  193. package/dist/infra/host-runtime-setup.js +86 -0
  194. package/dist/infra/host-runtime-setup.js.map +1 -0
  195. package/dist/infra/ipc.d.ts +1 -0
  196. package/dist/infra/ipc.d.ts.map +1 -1
  197. package/dist/infra/ipc.js +9 -0
  198. package/dist/infra/ipc.js.map +1 -1
  199. package/dist/onboarding.d.ts.map +1 -1
  200. package/dist/onboarding.js +67 -13
  201. package/dist/onboarding.js.map +1 -1
  202. package/dist/plugins/plugin-config.d.ts +5 -0
  203. package/dist/plugins/plugin-config.d.ts.map +1 -1
  204. package/dist/plugins/plugin-config.js +47 -1
  205. package/dist/plugins/plugin-config.js.map +1 -1
  206. package/dist/plugins/plugin-install.d.ts.map +1 -1
  207. package/dist/plugins/plugin-install.js +2 -1
  208. package/dist/plugins/plugin-install.js.map +1 -1
  209. package/dist/plugins/plugin-manager.d.ts.map +1 -1
  210. package/dist/plugins/plugin-manager.js +2 -1
  211. package/dist/plugins/plugin-manager.js.map +1 -1
  212. package/dist/providers/codex-constants.d.ts +2 -0
  213. package/dist/providers/codex-constants.d.ts.map +1 -0
  214. package/dist/providers/codex-constants.js +2 -0
  215. package/dist/providers/codex-constants.js.map +1 -0
  216. package/dist/providers/hybridai-bots.d.ts +1 -0
  217. package/dist/providers/hybridai-bots.d.ts.map +1 -1
  218. package/dist/providers/hybridai-bots.js +8 -11
  219. package/dist/providers/hybridai-bots.js.map +1 -1
  220. package/dist/security/instruction-integrity.js +1 -1
  221. package/dist/security/instruction-integrity.js.map +1 -1
  222. package/dist/security/runtime-secrets.d.ts +1 -1
  223. package/dist/security/runtime-secrets.d.ts.map +1 -1
  224. package/dist/security/runtime-secrets.js +2 -1
  225. package/dist/security/runtime-secrets.js.map +1 -1
  226. package/dist/session/session-context.d.ts.map +1 -1
  227. package/dist/session/session-context.js +1 -0
  228. package/dist/session/session-context.js.map +1 -1
  229. package/dist/session/session-reset.d.ts.map +1 -1
  230. package/dist/session/session-reset.js +3 -0
  231. package/dist/session/session-reset.js.map +1 -1
  232. package/dist/skills/skills-import.js +1 -1
  233. package/dist/skills/skills-import.js.map +1 -1
  234. package/dist/skills/skills.js +2 -1
  235. package/dist/skills/skills.js.map +1 -1
  236. package/dist/tui-banner.d.ts.map +1 -1
  237. package/dist/tui-banner.js +1 -0
  238. package/dist/tui-banner.js.map +1 -1
  239. package/dist/tui-clipboard.d.ts.map +1 -1
  240. package/dist/tui-clipboard.js +23 -7
  241. package/dist/tui-clipboard.js.map +1 -1
  242. package/dist/tui.d.ts.map +1 -1
  243. package/dist/tui.js +4 -2
  244. package/dist/tui.js.map +1 -1
  245. package/dist/utils/secret-prompt.d.ts +7 -0
  246. package/dist/utils/secret-prompt.d.ts.map +1 -0
  247. package/dist/utils/secret-prompt.js +102 -0
  248. package/dist/utils/secret-prompt.js.map +1 -0
  249. package/docs/chat.html +0 -1
  250. package/docs/development/README.md +14 -14
  251. package/docs/development/getting-started/authentication.md +3 -0
  252. package/docs/development/getting-started/installation.md +3 -0
  253. package/docs/development/internals/releasing.md +6 -2
  254. package/docs/development/reference/commands.md +21 -2
  255. package/docs/development/reference/configuration.md +14 -0
  256. package/docs/development/reference/diagnostics.md +3 -1
  257. package/docs/development/reference/faq.md +5 -4
  258. package/docs/imessage.md +338 -0
  259. package/docs/index.html +90 -26
  260. package/package.json +6 -2
  261. package/scripts/postinstall-container.mjs +184 -0
  262. package/skills/xlsx/SKILL.md +25 -25
  263. package/skills/xlsx/scripts/import_delimited.cjs +59 -37
  264. package/console/dist/assets/index-TCGsK-3Q.css +0 -1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,86 @@
2
2
 
3
3
  ## [Coming up]
4
4
 
5
+ ## [0.9.6](https://github.com/HybridAIOne/hybridclaw/tree/v0.9.6)
6
+
7
+ ### Changed
8
+
9
+ - **Release and docs alignment**: Refreshed the public README install section
10
+ with direct changelog and docs links, updated the static docs landing page so
11
+ its release highlights match the current shipped feature set, and aligned the
12
+ maintainer release guide with the changelog's `Coming up` workflow and the
13
+ docs surfaces that should be refreshed before a release.
14
+
15
+ ## [0.9.5](https://github.com/HybridAIOne/hybridclaw/tree/v0.9.5)
16
+
17
+ ### Added
18
+
19
+ - **Dual-backend iMessage channel**: Added `hybridclaw channels imessage setup`
20
+ plus gateway runtime support for local macOS delivery through `imsg` +
21
+ Messages `chat.db` and remote relay delivery through BlueBubbles webhooks
22
+ and REST sends.
23
+ - **Admin terminal page**: Added a browser-based `Terminal` page inside the
24
+ embedded admin console so operators can open a live PTY session from
25
+ `/admin/terminal` alongside the existing gateway and session views.
26
+ - **Local runtime config commands**: Added `hybridclaw config`,
27
+ `hybridclaw config check`, `hybridclaw config reload`, and
28
+ `hybridclaw config set <key> <value>`, plus matching local `/config`
29
+ slash commands for TUI and web sessions. The config view now shows the
30
+ active config file path, `set` validates immediately after saving, and
31
+ `reload` performs an in-process hot reload from disk.
32
+ - **HybridAI observability ingest**: Added runtime `observability.*` config
33
+ plus background forwarding of structured audit events such as `bot.set` to
34
+ the HybridAI observability ingest API with cached ingest tokens and restart
35
+ handling.
36
+
37
+ ### Changed
38
+
39
+ - **Built-in browser tool warnings**: Grouped the `browser_*` subtools into
40
+ one browser toolset in doctor/config diagnostics so unused-tool suggestions
41
+ are clearer before operators disable them.
42
+ - **Packaged install bootstrap and XLSX tooling**: Published installs now
43
+ bootstrap the packaged container runtime dependencies automatically, and the
44
+ bundled XLSX workflow now uses `xlsx-populate` instead of `exceljs` to avoid
45
+ a large deprecated transitive dependency chain.
46
+ - **Host-mode filesystem allowlist**: Host-mode agent access now uses an
47
+ explicit allowlist rooted at the user home directory, the gateway working
48
+ directory, `/tmp`, and configured bind or additional-mount host paths,
49
+ rather than an implicit project-root escape hatch.
50
+ - **Default HybridAI output budget**: Restored the default
51
+ `hybridai.maxTokens` value to `4096` while keeping it configurable through
52
+ the runtime config file and the new `config set` command surface.
53
+ - **Browser login profile handling**: Tightened the headed Chromium login flow
54
+ around the dedicated automation profile, including clearer automation-only
55
+ password-store intent and deferred Playwright cache directory creation.
56
+
57
+ ### Fixed
58
+
59
+ - **Admin terminal and iMessage hardening**: Tightened admin terminal session
60
+ transport and authentication, cleaned up stale browser sessions around
61
+ terminal/browser flows, stabilized iMessage self-chat handling, and restored
62
+ the local iMessage attributed-body fallback path.
63
+ - **Fresh-install runtime startup failures**: Fixed packaged fresh installs so
64
+ host/container workers no longer miss nested runtime dependencies, surfaced
65
+ worker startup crashes immediately in TUI instead of hanging on the spinner,
66
+ and added clearer runtime error text when the worker exits before producing
67
+ output.
68
+ - **Docker doctor guidance for sandboxed installs**: `hybridclaw doctor` now
69
+ treats Docker as a required dependency whenever the resolved sandbox mode is
70
+ not `host`, with explicit guidance to switch to host mode when Docker is not
71
+ available.
72
+ - **HybridAI recovery and auth-status handling**: Improved empty-completion and
73
+ retry-path diagnostics, cached parsed provider error bodies, simplified
74
+ debug serialization, removed unused parsed fields, and tightened
75
+ `auth status hybridai` output so it reports local auth/config state without
76
+ exposing the credentials file path.
77
+ - **Local slash-command consistency**: Added `/config` to the startup slash list, and aligned
78
+ `config check` so it validates only the runtime config file instead of
79
+ surfacing broader doctor hygiene warnings.
80
+ - **Plugin recovery workflows**: Tightened plugin enable/disable, config, and
81
+ reload rollback flows so disabling a broken or missing plugin no longer
82
+ requires discovery, no-op CLI output no longer claims the config changed,
83
+ and secondary plugin reload failures are surfaced more clearly.
84
+
5
85
  ## [0.9.4](https://github.com/HybridAIOne/hybridclaw/tree/v0.9.4)
6
86
 
7
87
  ### Added
package/README.md CHANGED
@@ -11,8 +11,8 @@
11
11
 
12
12
  <img width="540" height="511" alt="image" src="docs/hero.png" />
13
13
 
14
- Personal AI assistant for Discord, Microsoft Teams, WhatsApp, email, web, and
15
- terminal, powered by [HybridAI](https://hybridai.one).
14
+ Personal AI assistant for Discord, Microsoft Teams, iMessage, WhatsApp, email,
15
+ web, and terminal, powered by [HybridAI](https://hybridai.one).
16
16
 
17
17
  HybridClaw keeps one assistant brain across team chat, inbox, browser, and
18
18
  document workflows with shared memory, approvals, scheduling, and bundled
@@ -42,7 +42,11 @@ hybridclaw onboarding
42
42
  ```
43
43
 
44
44
  Prerequisites: Node.js 22. Docker is recommended when you want the default
45
- container sandbox.
45
+ container sandbox. The published install bootstraps the packaged container
46
+ runtime dependencies during `npm install -g`.
47
+ Release notes live in [CHANGELOG.md](./CHANGELOG.md), and the browsable
48
+ operator and maintainer manual lives under
49
+ [docs/development/README.md](./docs/development/README.md).
46
50
 
47
51
  ## HybridAI Advantage
48
52
 
@@ -55,7 +59,7 @@ container sandbox.
55
59
 
56
60
  ## Architecture
57
61
 
58
- - **Gateway service** (Node.js) — shared message/command handlers, SQLite persistence (KV + semantic + knowledge graph + canonical sessions + usage events), scheduler, heartbeat, web/API, and channel integrations for Discord, Microsoft Teams, WhatsApp, and email
62
+ - **Gateway service** (Node.js) — shared message/command handlers, SQLite persistence (KV + semantic + knowledge graph + canonical sessions + usage events), scheduler, heartbeat, web/API, and channel integrations for Discord, Microsoft Teams, iMessage, WhatsApp, and email
59
63
  - **TUI client** — thin client over HTTP (`/api/chat`, `/api/command`) with
60
64
  a structured startup banner that surfaces model, sandbox, gateway, and
61
65
  chatbot context before the first prompt
@@ -90,6 +94,7 @@ hybridclaw gateway start --foreground --sandbox=host
90
94
 
91
95
  # If msteams.enabled=true and MSTEAMS_APP_PASSWORD is configured, gateway auto-connects to Microsoft Teams.
92
96
  # If DISCORD_TOKEN is set, gateway auto-connects to Discord.
97
+ # If imessage.enabled=true, gateway auto-connects to iMessage using the configured backend.
93
98
  # If email.enabled=true and EMAIL_PASSWORD is configured, gateway auto-connects to Email.
94
99
  # If linked WhatsApp auth exists, gateway auto-connects to WhatsApp.
95
100
 
@@ -104,7 +109,9 @@ hybridclaw tui
104
109
 
105
110
  # Embedded admin console
106
111
  # open http://127.0.0.1:9090/admin
107
- # Includes Dashboard, Gateway, Sessions, Jobs, Bindings, Models, Scheduler, MCP, Audit, Skills, Plugins, Tools, and Config
112
+ # Browser terminal page
113
+ # open http://127.0.0.1:9090/admin/terminal
114
+ # Includes Dashboard, Terminal, Gateway, Sessions, Jobs, Bindings, Models, Scheduler, MCP, Audit, Skills, Plugins, Tools, and Config
108
115
  # If WEB_API_TOKEN is unset, localhost access opens without a login prompt
109
116
  # If WEB_API_TOKEN is set, /chat, /agents, and /admin all prompt for the same token
110
117
  ```
@@ -151,10 +158,11 @@ hybridclaw local configure ollama llama3.2
151
158
  - `hybridclaw auth login huggingface` accepts `--api-key`, falls back to `HF_TOKEN`, or prompts you to paste the token, then enables the provider and can set the global default model.
152
159
  - `hybridclaw auth login local` configures Ollama, LM Studio, or vLLM in `~/.hybridclaw/config.json`.
153
160
  - `hybridclaw auth login msteams` enables Microsoft Teams, stores `MSTEAMS_APP_PASSWORD` in `~/.hybridclaw/credentials.json`, and can prompt for the app id, app password, and optional tenant id.
161
+ - `hybridclaw auth status hybridai` reports the local auth source, masked API key, active config file, base URL, and default model without printing the credentials file path.
154
162
  - `hybridclaw auth logout local` disables configured local backends and clears any saved vLLM API key.
155
163
  - `hybridclaw auth logout msteams` clears the stored Teams app password and disables the Teams integration in config.
156
164
  - `hybridclaw auth whatsapp reset` clears linked WhatsApp Web auth without starting a new pairing session.
157
- - HybridAI, OpenRouter, Hugging Face, Discord, email, and Teams secrets are stored in `~/.hybridclaw/credentials.json`. Codex OAuth credentials are stored separately in `~/.hybridclaw/codex-auth.json`.
165
+ - HybridAI, OpenRouter, Hugging Face, Discord, email, Teams, and BlueBubbles iMessage secrets are stored in `~/.hybridclaw/credentials.json`. Codex OAuth credentials are stored separately in `~/.hybridclaw/codex-auth.json`.
158
166
  - Only one running HybridClaw process should own `~/.hybridclaw/credentials/whatsapp` at a time. If WhatsApp Web shows duplicate Chrome/Ubuntu linked devices or reconnect/auth drift starts, stop the extra process, run `hybridclaw auth whatsapp reset`, then pair again with `hybridclaw channels whatsapp setup`.
159
167
  - Use `hybridclaw help`, `hybridclaw help auth`, `hybridclaw help openrouter`, `hybridclaw help huggingface`, or `hybridclaw help local` for CLI-specific reference output.
160
168
 
@@ -168,6 +176,16 @@ See [docs/msteams.md](./docs/msteams.md) for the full setup flow, including:
168
176
  - local tunnel setup
169
177
  - DM and channel smoke tests
170
178
 
179
+ ## Setting Up iMessage
180
+
181
+ See [docs/imessage.md](./docs/imessage.md) for the full setup flow, including:
182
+
183
+ - local macOS mode with `imsg` and Messages `chat.db`
184
+ - remote/cloud mode with BlueBubbles webhooks + REST sends
185
+ - `imessage.*` config examples for both backends
186
+ - `IMESSAGE_PASSWORD` secret handling for BlueBubbles
187
+ - DM/group policy notes and smoke-test steps
188
+
171
189
  ## Model Selection
172
190
 
173
191
  Codex models use the `openai-codex/` prefix. OpenRouter models use the `openrouter/` prefix. Hugging Face router models use the `huggingface/` prefix. The default shipped Codex model is `openai-codex/gpt-5-codex`.
@@ -210,6 +228,7 @@ Runtime model:
210
228
  - `hybridclaw gateway` is the core process and should run first.
211
229
  - If `msteams.enabled` is true and `MSTEAMS_APP_PASSWORD` is configured, Microsoft Teams runs inside gateway automatically.
212
230
  - If `DISCORD_TOKEN` is set, Discord runs inside gateway automatically.
231
+ - If `imessage.enabled` is true, iMessage runs inside gateway automatically using either the local macOS backend or the configured BlueBubbles server.
213
232
  - If `email.enabled` is true and `EMAIL_PASSWORD` is configured, Email runs inside gateway automatically.
214
233
  - If linked WhatsApp auth exists under `~/.hybridclaw/credentials/whatsapp`, WhatsApp runs inside gateway automatically.
215
234
  - `hybridclaw tui` is a thin client that connects to the gateway.
@@ -227,21 +246,26 @@ HybridClaw creates `~/.hybridclaw/config.json` on first run and hot-reloads most
227
246
  - Runtime state lives under `~/.hybridclaw/` (`config.json`, `credentials.json`, `data/hybridclaw.db`, audit/session files). Set `HYBRIDCLAW_DATA_DIR` to an absolute path to relocate the full runtime home, including browser profiles and agent workspaces.
228
247
  - HybridClaw does not keep runtime state in the current working directory. If `./.env` exists, supported secrets are migrated once into `~/.hybridclaw/credentials.json`.
229
248
  - `container.*` controls execution isolation, including `sandboxMode`, `memory`, `memorySwap`, `cpus`, `network`, `binds`, and additional mounts.
249
+ - `hybridclaw config` prints the active runtime config path and current config, `config check` validates only the config file itself, `config reload` performs an immediate in-process hot reload, and `config set <key> <value>` updates one existing dotted key path and re-validates the result.
230
250
  - Use `container.binds` for explicit host-to-container mounts in `host:container[:ro|rw]` format. Mounted paths appear inside the sandbox under `/workspace/extra/<container>`.
251
+ - In `host` sandbox mode, the agent can access the user home directory, the gateway working directory, `/tmp`, and any host paths explicitly added through `container.binds` or `container.additionalMounts`.
231
252
  - `mcpServers.*` declares Model Context Protocol servers that HybridClaw connects to per session and exposes as namespaced tools (`server__tool`).
232
253
  - `sessionReset.*` controls automatic daily and idle session expiry. The default policy resets both daily and after 24 hours idle at `04:00` in the gateway host's local timezone; set `sessionReset.defaultPolicy.mode` to `none` to disable automatic resets.
233
254
  - `sessionRouting.*` controls DM continuity scope. The default `per-channel-peer` mode keeps direct messages isolated by transport and peer identity; `per-linked-identity` plus `sessionRouting.identityLinks` can collapse verified aliases onto one shared main session.
234
255
  - `agents.defaultAgentId` selects the default agent for new requests and fresh web sessions when the user does not pin an agent explicitly.
256
+ - `hybridai.maxTokens` controls the default HybridAI completion output budget. The shipped default is `4096`, and it can be adjusted live with `hybridclaw config set hybridai.maxTokens <n>`.
235
257
  - `skills.disabled` and `skills.channelDisabled.{discord,msteams,whatsapp,email}` control global and per-channel skill availability. Use `hybridclaw skill enable|disable <name> [--channel <kind>]` or the TUI `/skill config` checklist to manage them.
236
258
  - `plugins.list[]` controls plugin overrides such as `enabled`, custom `path`, and top-level `config` values. Use `hybridclaw plugin config <plugin-id> [key] [value|--unset]` for focused edits without rewriting the full config file.
259
+ - `observability.*` controls HybridAI observability ingest, including the target base URL, bot and agent ids, flush interval, and batch size for structured audit event forwarding.
237
260
  - `adaptiveSkills.*` controls observation, inspection, amendment staging, and rollback for the self-improving skill loop. See [docs/development/extensibility/adaptive-skills.md](./docs/development/extensibility/adaptive-skills.md) for the operator workflow.
261
+ - `imessage.*` controls the dual-backend iMessage transport. Use `backend: "local"` on macOS with `imsg` + `chat.db`, or `backend: "bluebubbles"` for a remote Mac relay via BlueBubbles. Prefer storing the BlueBubbles password in `~/.hybridclaw/credentials.json` as `IMESSAGE_PASSWORD` instead of plaintext config.
238
262
  - `email.pollIntervalMs` defaults to `30000` (30 seconds) and is clamped to a minimum of `1000`.
239
263
  - `ops.webApiToken` (or `WEB_API_TOKEN`) gates the built-in `/chat`, `/agents`, and `/admin` surfaces plus the admin API. When unset, localhost browser access stays open without a login prompt.
240
264
  - `mcpServers.*.env` and `mcpServers.*.headers` are currently written to `~/.hybridclaw/config.json` as plain text. Use low-privilege tokens only, set `chmod 700 ~/.hybridclaw && chmod 600 ~/.hybridclaw/config.json`, and prefer `host` sandbox mode for stdio MCP servers that depend on host-installed tools.
241
265
  - `media.audio` controls shared inbound audio transcription. By default it auto-detects local CLIs first (`sherpa-onnx-offline`, `whisper-cli`, `whisper`), then `gemini`, then provider keys (`openai`, `groq`, `deepgram`, `google`).
242
266
  - `whisper-cli` auto-detect also needs a whisper.cpp model file. If the binary exists but HybridClaw still skips local transcription, set `WHISPER_CPP_MODEL` to a local `ggml-*.bin` model path.
243
267
  - If no transcript backend is available, the container tries native model audio input before tool-use fallback for supported local providers. Today that fallback is enabled for `vllm` sessions and uses the original current-turn audio attachment.
244
- - Keep runtime secrets in `~/.hybridclaw/credentials.json` (`HYBRIDAI_API_KEY`, `OPENROUTER_API_KEY`, `HF_TOKEN`, `OPENAI_API_KEY`, `GROQ_API_KEY`, `DEEPGRAM_API_KEY`, `GEMINI_API_KEY`, `GOOGLE_API_KEY`, `DISCORD_TOKEN`, `EMAIL_PASSWORD`, `MSTEAMS_APP_PASSWORD`). Codex OAuth sessions are stored separately in `~/.hybridclaw/codex-auth.json`.
268
+ - Keep runtime secrets in `~/.hybridclaw/credentials.json` (`HYBRIDAI_API_KEY`, `OPENROUTER_API_KEY`, `HF_TOKEN`, `OPENAI_API_KEY`, `GROQ_API_KEY`, `DEEPGRAM_API_KEY`, `GEMINI_API_KEY`, `GOOGLE_API_KEY`, `DISCORD_TOKEN`, `EMAIL_PASSWORD`, `IMESSAGE_PASSWORD`, `MSTEAMS_APP_PASSWORD`). Codex OAuth sessions are stored separately in `~/.hybridclaw/codex-auth.json`.
245
269
  - Trust-model acceptance is stored in `~/.hybridclaw/config.json` under `security.*` and is required before runtime starts. In headless environments, set `HYBRIDCLAW_ACCEPT_TRUST=true` to persist acceptance automatically before credential checks run.
246
270
  - See [TRUST_MODEL.md](./TRUST_MODEL.md) for onboarding acceptance policy and [SECURITY.md](./SECURITY.md) for technical security guidelines.
247
271
  - For contributor workflow, see [CONTRIBUTING.md](./CONTRIBUTING.md). For deeper runtime, skills, release, voice/TTS, and maintainer reference docs, see [docs/development/README.md](./docs/development/README.md).
@@ -543,10 +567,12 @@ CLI runtime commands:
543
567
  - `hybridclaw auth login [provider] ...` — Namespaced provider setup/login entrypoint
544
568
  - `hybridclaw auth status <provider>` — Show provider status for `hybridai`, `codex`, `openrouter`, `local`, or `msteams`
545
569
  - `hybridclaw auth logout <provider>` — Clear provider credentials or disable local backends/Teams
570
+ - `hybridclaw config`, `check`, `reload`, `set <key> <value>` — Inspect, validate, hot-reload, or edit the local runtime config file
546
571
  - `hybridclaw auth login msteams [--app-id <id>] [--app-password <secret>] [--tenant-id <id>]` — Enable Microsoft Teams, persist the app secret, and print webhook next steps
547
572
  - `hybridclaw auth whatsapp reset` — Clear linked WhatsApp auth so the account can be re-paired cleanly
548
573
  - `hybridclaw channels discord setup [--token <token>] [--allow-user-id <snowflake>]... [--prefix <prefix>]` — Prepare restricted command-only Discord config and print bot/token next steps
549
574
  - `hybridclaw channels email setup [--address <email>] [--password <password>] [--imap-host <host>] [--imap-port <port>] [--imap-secure|--no-imap-secure] [--smtp-host <host>] [--smtp-port <port>] [--smtp-secure|--no-smtp-secure] [--folder <name>]... [--allow-from <email|*@domain|*>]... [--poll-interval-ms <ms>] [--text-chunk-limit <chars>] [--media-max-mb <mb>]` — Configure IMAP/SMTP email delivery, optionally prompt for missing credentials, default to a 30-second IMAP poll interval, and save `EMAIL_PASSWORD`
575
+ - `hybridclaw channels imessage setup [--backend <local|remote>] [--allow-from <phone|email|chat:id>]... [--server-url <url>] [--password <password>] [--cli-path <path>] [--db-path <path>] [--webhook-path <path>] [--allow-private-network]` — Configure either the local macOS `imsg` backend or the BlueBubbles relay backend, store `IMESSAGE_PASSWORD` when needed, and keep inbound iMessage private-by-default unless handles are allowlisted
550
576
  - `hybridclaw channels whatsapp setup [--reset] [--allow-from <+E164>]...` — Prepare private-by-default WhatsApp config, enable the default `👀` ack reaction, optionally wipe stale auth, open a temporary pairing session, and print the QR code
551
577
  - `hybridclaw browser login [--url <url>]`, `status`, `reset` — Manage the persistent browser profile used for authenticated web automation
552
578
  - `hybridclaw local status` — Show current local backend config and default model
@@ -561,6 +587,7 @@ CLI runtime commands:
561
587
  - `hybridclaw skill install <skill> [install-id]` — Run a declared skill dependency installer
562
588
  - `hybridclaw plugin list` — Show discovered plugins, enabled state, registered tools/hooks, and load errors
563
589
  - `hybridclaw plugin config <plugin-id> [key] [value|--unset]` — Inspect or change one top-level `plugins.list[].config` override
590
+ - `hybridclaw plugin enable <plugin-id>` / `disable <plugin-id>` — Toggle one top-level `plugins.list[].enabled` override for local plugin recovery
564
591
  - `hybridclaw plugin install <path|npm-spec>`, `reinstall`, `uninstall` — Manage plugins installed under `~/.hybridclaw/plugins`
565
592
  - `hybridclaw update [status|--check] [--yes]` — Check for updates and upgrade global npm installs (source checkouts get git-based update instructions)
566
593
  - `hybridclaw audit ...` — Verify and inspect structured audit trail (`recent`, `search`, `approvals`, `verify`, `instructions`)
@@ -603,9 +630,12 @@ Up/Down on an empty prompt recalls earlier prompts. Use `/agent`, `/agent list`,
603
630
  the agent/default model chain, and `/model info` to inspect the active scope.
604
631
  `/status` shows both the current session and agent; `/compact` handles session
605
632
  compaction; `/reset` runs the confirmed workspace reset flow; `/skill config`
606
- opens the interactive skill availability checklist; `/plugin list`,
607
- `/plugin config ...`, and `/plugin reload` manage runtime plugins; and
608
- `/mcp ...` manages runtime MCP servers. Press `Ctrl-C` or `Ctrl-D` twice within
609
- five seconds to exit. When a TUI session exits, HybridClaw prints the
610
- input/output token split, tool/file totals, and a ready-to-run
633
+ opens the interactive skill availability checklist; `/config`, `/config check`,
634
+ `/config reload`, and `/config set <key> <value>` manage the local runtime
635
+ config; `/auth status hybridai` shows local HybridAI auth/config state;
636
+ `/plugin list`, `/plugin config ...`, `/plugin enable`, `/plugin disable`,
637
+ `/plugin install`, `/plugin reinstall`, and `/plugin reload` manage runtime
638
+ plugins; and `/mcp ...` manages runtime MCP servers. Press `Ctrl-C` or `Ctrl-D`
639
+ twice within five seconds to exit. When a TUI session exits, HybridClaw prints
640
+ the input/output token split, tool/file totals, and a ready-to-run
611
641
  `hybridclaw tui --resume <sessionId>` command for that session.
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": 17,
2
+ "version": 18,
3
3
  "security": {
4
4
  "trustModelAccepted": false,
5
5
  "trustModelAcceptedAt": "",
@@ -132,6 +132,24 @@
132
132
  "ackReaction": "👀",
133
133
  "mediaMaxMb": 20
134
134
  },
135
+ "imessage": {
136
+ "enabled": false,
137
+ "backend": "local",
138
+ "cliPath": "imsg",
139
+ "dbPath": "/Users/example/Library/Messages/chat.db",
140
+ "pollIntervalMs": 2500,
141
+ "serverUrl": "https://bluebubbles.example.com",
142
+ "password": "",
143
+ "webhookPath": "/api/imessage/webhook",
144
+ "allowPrivateNetwork": false,
145
+ "dmPolicy": "allowlist",
146
+ "groupPolicy": "disabled",
147
+ "allowFrom": [],
148
+ "groupAllowFrom": [],
149
+ "textChunkLimit": 4000,
150
+ "debounceMs": 2500,
151
+ "mediaMaxMb": 20
152
+ },
135
153
  "email": {
136
154
  "enabled": false,
137
155
  "imapHost": "",
@@ -0,0 +1 @@
1
+ :root{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--page-bg:#fff;--sidebar-bg:#f1f5f9;--panel-bg:#fff;--panel-muted:#f8fafc;--line:#e5e7eb;--line-strong:#d1d5db;--text:#1f2937;--muted:#64748b;--accent:#4a6cf7;--accent-soft:#eef2ff;--success:#0f766e;--success-soft:#ecfdf5;--danger:#b42318;--danger-soft:#fef3f2;--radius-lg:14px;--radius-md:10px;--radius-sm:8px;--sans:system-ui, ui-sans-serif, -apple-system, BlinkMacSystemFont, Inter, NotoSansHans, sans-serif}*{box-sizing:border-box}html,body,#root{min-height:100%}body{background:var(--page-bg);color:var(--text);font-family:var(--sans);margin:0}button,input,select,textarea{font:inherit}code{font-family:SFMono-Regular,JetBrains Mono,Fira Code,monospace}.app-frame{background:var(--page-bg);grid-template-columns:216px minmax(0,1fr);min-height:100vh;display:grid}.sidebar{background:var(--sidebar-bg);border-right:1px solid var(--line);flex-direction:column;justify-content:space-between;gap:24px;min-height:100vh;padding:20px 16px;display:flex;overflow-y:auto}.main-panel{flex-direction:column;min-width:0;min-height:100dvh;padding:24px;display:flex}.brand-block,.page-content,.page-stack,.detail-stack,.stack-form,.list-stack,.field,.config-section{gap:12px;display:grid}.page-content{flex:auto;min-height:0}.brand-block{padding:4px 8px}.brand-title{align-items:center;gap:8px;display:flex}.brand-block h1,.topbar h2,.panel h4,.login-card h1{letter-spacing:-.02em;margin:0;font-weight:600}.brand-block h1{font-size:1.1rem}.topbar h2{font-size:clamp(1.9rem,2.4vw,2.35rem)}.panel h4{font-size:1rem}.eyebrow{text-transform:uppercase;letter-spacing:.08em;color:var(--muted);margin:0;font-size:.74rem;font-weight:700}.supporting-text,.metric-card small,.list-row small,.summary-block span,.key-value-grid span{color:var(--muted);margin:0}.inline-popover{margin-top:4px;display:inline-block;position:relative}.inline-popover summary{list-style:none}.inline-popover summary::-webkit-details-marker{display:none}.inline-popover-trigger{color:var(--muted);cursor:pointer;text-decoration:underline;-webkit-text-decoration-color:var(--line-strong);text-decoration-color:var(--line-strong);text-underline-offset:2px;background:0 0;border:0;align-items:center;gap:6px;padding:0;font-size:.875rem;line-height:1.35;display:inline-flex}.inline-popover-trigger:hover{color:var(--text)}.inline-popover-panel{z-index:20;border:1px solid var(--line);border-radius:var(--radius-md);background:var(--panel-bg);width:min(360px,70vw);padding:12px;position:absolute;top:calc(100% + 8px);left:0;box-shadow:0 12px 32px #0f172a1f}.inline-popover-header{color:var(--muted);text-transform:uppercase;letter-spacing:.08em;margin-bottom:8px;font-size:.8rem;font-weight:700}.inline-popover-list{gap:10px;display:grid}.inline-popover-entry{gap:4px;display:grid}.inline-popover-entry strong{font-size:.88rem;line-height:1.3}.inline-popover-entry small,.inline-popover-entry p{color:var(--muted);margin:0}.inline-popover-entry p{color:var(--text);overflow-wrap:anywhere;word-break:break-word}.nav-group{gap:2px;margin-top:16px;display:grid}.nav-section{gap:6px;margin-top:18px;display:grid}.nav-section .nav-group{margin-top:0}.nav-link{border-radius:var(--radius-sm);color:var(--text);border:1px solid #0000;align-items:center;gap:8px;padding:8px 12px;font-weight:500;text-decoration:none;display:flex}.nav-link-icon{flex:none;justify-content:center;align-items:center;width:16px;height:16px;display:inline-flex}.nav-link-icon svg{width:16px;height:16px}.nav-link:hover{background:var(--panel-bg);border-color:var(--line)}.nav-link.active{background:var(--panel-bg);border-color:var(--line);color:var(--accent)}.sidebar-footer,.button-row,.header-actions{flex-wrap:wrap;align-items:center;gap:10px;display:flex}.sidebar-footer{flex-direction:column;align-items:stretch}.sidebar-meta-chip{align-self:flex-start}.topbar{justify-content:space-between;align-items:center;gap:16px;margin-bottom:14px;padding-bottom:12px;display:flex}.topbar-title{min-width:0}.topbar-title h2{line-height:1.05}.view-switch{border:1px solid var(--line);background:var(--panel-muted);border-radius:999px;flex-wrap:wrap;align-items:center;gap:8px;padding:6px;display:inline-flex}.view-switch-link{color:var(--muted);border-radius:999px;align-items:center;gap:8px;padding:9px 14px;font-weight:600;text-decoration:none;display:inline-flex}.view-switch-link:hover{color:var(--text)}.view-switch-link.active{background:var(--panel-bg);color:var(--accent);box-shadow:0 1px 2px #0f172a14}.meta-chip,.status-pill{border:1px solid var(--line);background:var(--panel-bg);color:var(--muted);border-radius:999px;align-items:center;gap:8px;padding:7px 10px;font-size:.84rem;font-weight:500;display:inline-flex}.brand-block .status-pill{justify-self:start}.status-pill-success{background:var(--success-soft);color:var(--success);border-color:#bbf7d0}.status-dot{background:#94a3b8;border-radius:999px;width:8px;height:8px}.status-dot.live{background:var(--accent)}.status-dot-success{background:var(--success)}.status-dot-danger{background:var(--danger)}.page-stack,.detail-stack,.stack-form,.list-stack,.page-content{gap:20px}.page-header{justify-content:space-between;align-items:center;gap:18px;display:flex}.page-header-description{max-width:62ch}.panel{border-radius:var(--radius-lg);border:1px solid var(--line);background:var(--panel-bg);padding:8px}.terminal-page{flex-direction:column;flex:auto;gap:10px;height:100%;min-height:0;display:flex}.terminal-panel-body{flex-direction:column;flex:auto;gap:16px;min-width:0;min-height:0;display:flex}.terminal-page .page-header .button-row{justify-content:flex-end}.terminal-page .page-header .status-pill{margin-right:6px}.terminal-page .page-header .header-actions{justify-content:flex-end;width:100%}.terminal-page .page-header{justify-content:flex-end}.terminal-page .page-header>span:first-child{display:none}.terminal-page .page-header .button-row{margin-bottom:4px}.terminal-shell{background:#0f172a;border-radius:12px;flex:auto;width:100%;min-height:320px;display:flex;position:relative;overflow:hidden}.terminal-host{flex:auto;min-width:0;height:calc(100% - 12px);min-height:0;margin-bottom:12px;padding:4px 6px;overflow:hidden}.terminal-host .xterm{width:100%;min-width:0;max-width:100%;height:100%;overflow:hidden}.terminal-host .xterm-viewport{overflow-x:hidden}.terminal-host .xterm-screen{width:100%;max-width:100%}.terminal-empty-state{text-align:center;color:#cbd5e1;background:linear-gradient(#0f172ac2,#0f172aeb);place-items:center;padding:24px;display:grid;position:absolute;inset:0}.terminal-empty-copy{white-space:nowrap}.terminal-error-banner{margin-top:16px}@media (width<=960px){.terminal-panel-body{gap:12px}}.panel.warm,.metric-card,.config-section,.empty-state,.summary-block,.key-value-grid div,.usage-stack{background:var(--panel-muted)}.panel-header{margin-bottom:16px}.metric-grid,.two-column-grid,.field-grid,.usage-grid,.config-grid,.key-value-grid{gap:16px;display:grid}.metric-grid{grid-template-columns:repeat(4,minmax(0,1fr))}.two-column-grid{grid-template-columns:minmax(0,1.1fr) minmax(340px,.9fr)}.usage-grid,.field-grid,.config-grid,.key-value-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.metric-card{border-radius:var(--radius-md);border:1px solid var(--line);gap:6px;padding:14px 16px;display:grid}.metric-card strong{font-size:1.8rem;font-weight:700}.list-row,.selectable-row{border-radius:var(--radius-md);border:1px solid var(--line);background:var(--panel-bg);justify-content:space-between;align-items:flex-start;gap:12px;padding:12px 14px;display:flex}.list-row>div{flex:auto;gap:4px;min-width:0;display:grid}.list-row strong{overflow-wrap:anywhere;word-break:break-word;line-height:1.25;display:block}.list-row small{line-height:1.35;display:block}.list-row>span:last-child{white-space:nowrap;flex:none;padding-left:12px}.list-status{align-items:center;gap:8px;font-weight:500;display:inline-flex}.list-status-success{color:var(--success)}.list-status-danger{color:var(--danger)}.row-status-stack{text-align:right;flex:none;justify-items:end;gap:6px;padding-left:12px;display:grid}.row-status-stack small{color:var(--muted)}.selectable-row{text-align:left;cursor:pointer;width:100%;min-width:0}.selectable-row>div{flex:auto;gap:4px;min-width:0;display:grid}.selectable-row strong,.selectable-row small{display:block}.selectable-row strong{overflow-wrap:anywhere;word-break:break-word;line-height:1.25}.selectable-row small{line-height:1.35}.selectable-row.active{border-color:var(--accent);background:var(--accent-soft)}.table-shell{overflow-x:auto}table{border-collapse:collapse;width:100%}th,td{border-bottom:1px solid var(--line);text-align:left;vertical-align:top;padding:12px 10px}th{text-transform:uppercase;letter-spacing:.08em;color:var(--muted);font-size:.75rem}.field,.toggle-row,.config-section{gap:8px}.field input,.field select,.field textarea,.compact-search{border-radius:var(--radius-sm);border:1px solid var(--line-strong);background:var(--panel-bg);width:100%;color:var(--text);padding:10px 12px}.field textarea,.code-editor{resize:vertical}.toggle-row{grid-template-columns:auto 1fr;align-items:center;display:grid}.boolean-field{align-items:start}.boolean-pill{border:1px solid var(--line);text-transform:lowercase;border-radius:999px;align-items:center;gap:8px;width:fit-content;padding:6px 10px;font-size:.82rem;font-weight:600;display:inline-flex}.boolean-pill.is-on{background:var(--success-soft);color:var(--success);border-color:#bbf7d0}.boolean-pill.is-off{background:var(--panel-muted);border-color:var(--line-strong);color:var(--muted)}.boolean-pill-dot{background:currentColor;border-radius:999px;width:8px;height:8px}.binary-toggle{border:1px solid var(--line-strong);background:var(--panel-bg);border-radius:999px;align-items:center;width:fit-content;display:inline-flex;overflow:hidden}.binary-toggle-button{color:var(--muted);cursor:pointer;text-transform:lowercase;background:0 0;border:0;padding:8px 12px}.binary-toggle-button+.binary-toggle-button{border-left:1px solid var(--line-strong)}.binary-toggle-button.active.is-on{background:var(--success-soft);color:var(--success)}.binary-toggle-button.active.is-off{background:var(--panel-muted);color:var(--text)}.binary-toggle-button:disabled{cursor:default;opacity:.65}.config-section{border-radius:var(--radius-md);border:1px solid var(--line);padding:16px}.primary-button,.ghost-button,.danger-button{border-radius:var(--radius-sm);cursor:pointer;border:1px solid #0000;padding:9px 12px}.primary-button{background:var(--accent);border-color:var(--accent);color:#fff}.ghost-button{background:var(--panel-bg);border-color:var(--line-strong);color:var(--text)}.danger-button{background:var(--danger-soft);color:var(--danger);border-color:#fecaca}.table-link-button{color:var(--text);font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;padding:0;font-weight:700}.table-link-button:hover{color:var(--accent)}.skill-review-actions{flex-wrap:wrap;justify-content:flex-end;align-items:center;gap:8px;display:flex}.empty-state,.success-banner,.error-banner,.summary-block{border-radius:var(--radius-md);border:1px solid var(--line);padding:14px 16px}.empty-state{color:var(--muted)}.empty-state.error,.error-banner{background:var(--danger-soft);color:var(--danger);border-color:#fecaca}.success-banner{background:var(--success-soft);color:var(--success);border-color:#a7f3d0}.summary-block p{margin:0;line-height:1.55}.summary-block-header,.jobs-output-actions{justify-content:space-between;align-items:center;gap:10px;display:flex}.jobs-output-list{gap:12px;display:grid}.jobs-output-card{border:1px solid var(--line);border-radius:var(--radius-md);background:var(--panel-bg);gap:10px;padding:12px;display:grid}.jobs-output-actions small{color:var(--muted)}.jobs-output-pre{white-space:pre-wrap;word-break:break-word;overflow-wrap:anywhere;font:inherit;margin:0;line-height:1.55}.payload-block{white-space:pre-wrap;word-break:break-word;max-height:480px;margin:0;font-family:SFMono-Regular,JetBrains Mono,Fira Code,monospace;font-size:.88rem;line-height:1.45;overflow:auto}.sessions-layout,.selectable-list,.sessions-layout .panel,.sessions-layout .detail-stack,.session-row-main,.key-value-grid div{min-width:0}.session-row-main{flex:auto}.session-row-main strong,.session-row-meta,.key-value-grid strong{overflow-wrap:anywhere;word-break:break-word;display:block}.session-row-main strong{line-height:1.25}.session-row-meta{margin-top:4px;font-size:.95rem;line-height:1.35}.session-row-time{white-space:nowrap;color:var(--muted);flex:none;font-size:.95rem}.key-value-grid div,.usage-stack{border-radius:var(--radius-md);border:1px solid var(--line);gap:4px;padding:14px;display:grid}.usage-stack strong{font-size:1.3rem}.table-shell td strong,.table-shell td small{display:block}.table-shell td strong{overflow-wrap:anywhere;word-break:break-word;line-height:1.25}.table-shell td small{margin-top:4px;line-height:1.35}.login-shell{background:var(--panel-muted);place-items:center;min-height:100vh;padding:24px;display:grid}.login-card{border-radius:var(--radius-lg);border:1px solid var(--line);background:var(--panel-bg);width:min(480px,100%);padding:24px}.login-card h1{font-size:1.75rem}.compact-search{min-width:240px}.jobs-column-header{align-items:center;display:flex}.jobs-column{min-width:0}.jobs-columns,.jobs-column-body{gap:12px;display:grid}.jobs-card-pill{border-radius:999px;justify-content:center;align-items:center;font-size:.78rem;font-weight:700;display:inline-flex}.jobs-header-search{flex:0 260px;min-width:180px}.page-header .header-actions{flex-wrap:nowrap;justify-content:flex-end;width:auto}.page-header .header-actions .primary-button{flex:none}.jobs-board-layout{border:1px solid var(--line);background:var(--panel-bg);border-radius:18px;grid-template-columns:minmax(0,1fr);min-width:0;min-height:720px;display:grid;overflow:hidden;box-shadow:0 10px 32px #0f172a0d}.jobs-board-layout.has-detail{grid-template-columns:minmax(0,1fr) 320px}.jobs-card strong,.jobs-card p{overflow-wrap:anywhere;word-break:break-word}.jobs-card strong,.jobs-card p,.jobs-card small{margin:0}.jobs-card p,.jobs-card small{color:var(--muted)}.jobs-columns{border-right:1px solid var(--line);background:#fcfcfd;grid-auto-columns:minmax(220px,1fr);grid-auto-flow:column;align-items:stretch;gap:4px;padding:12px 14px;display:grid;overflow-x:auto}.jobs-column{--jobs-column-rgb:203, 213, 225;background:rgba(var(--jobs-column-rgb), .04);border:0;border-radius:16px;grid-template-rows:auto minmax(0,1fr);gap:10px;min-width:0;margin:0;padding:10px 8px;display:grid}.jobs-column.drop-target{background:#4a6cf714;box-shadow:inset 0 0 0 1px #4a6cf733}.jobs-column-backlog{--jobs-column-rgb:203, 213, 225}.jobs-column-in_progress{--jobs-column-rgb:147, 197, 253}.jobs-column-review{--jobs-column-rgb:252, 211, 77}.jobs-column-done{--jobs-column-rgb:134, 239, 172}.jobs-column-cancelled{--jobs-column-rgb:252, 165, 165}.jobs-column-header{border:1px solid var(--line);background:rgba(var(--jobs-column-rgb), .08);border-radius:14px;justify-content:space-between;gap:10px;padding:10px 12px;font-size:.95rem}.jobs-column-header span{background:var(--panel-muted);color:var(--muted);border-radius:999px;padding:2px 7px;font-size:.8rem;font-weight:700}.jobs-column-body{align-content:start;min-width:0;max-height:640px;padding-right:4px;overflow-y:auto}.jobs-column-empty{border:1px dashed var(--line-strong);color:var(--muted);background:#f8fafca6;border-radius:12px;padding:12px}.jobs-card{background:var(--panel-bg);border:1px solid #ebeef3;border-radius:16px;gap:8px;padding:12px;display:grid;box-shadow:0 1px 2px #0f172a0a}.jobs-card-top{justify-content:space-between;align-items:flex-start;gap:8px;display:flex}.jobs-card.tone-progress{border-color:#bfdbfe}.jobs-card.tone-review{border-color:#fcd34d}.jobs-card.tone-success{border-color:#bbf7d0}.jobs-card.tone-danger{border-color:#fecaca}.jobs-card strong{font-size:.95rem;line-height:1.25}.jobs-card p{min-height:2.5em;font-size:.92rem;line-height:1.35}.jobs-card small{text-transform:uppercase;letter-spacing:.04em;font-size:.78rem}.jobs-card-pill{color:#109669;background:#eafaf3;width:fit-content;padding:5px 8px}.jobs-card-frame{width:100%;display:block}.jobs-card-frame.drop-target .jobs-card{box-shadow:0 0 0 1px #4a6cf72e}.jobs-card-shell{position:relative}.jobs-card-button{text-align:left;cursor:pointer;background:0 0;border:0;width:100%;padding:0;display:block}.jobs-card-button:focus-visible .jobs-card{border-color:var(--accent);box-shadow:0 0 0 1px #4a6cf72e}.jobs-card-shell.draggable{cursor:grab}.jobs-inline-trigger{width:100%;min-width:0;color:var(--text);font:inherit;text-align:left;overflow-wrap:anywhere;word-break:break-word;cursor:pointer;background:0 0;border:0;padding:0;font-weight:700}.jobs-inline-trigger:disabled{cursor:default}.jobs-inline-select{box-sizing:border-box;width:100%;min-width:0;max-width:100%}.jobs-card-frame.dragging{opacity:.58}.jobs-card-frame.dragging .jobs-card{border-style:dashed}.jobs-card-shell.active .jobs-card{border-color:var(--accent);box-shadow:0 0 0 1px #4a6cf72e}.jobs-detail{background:var(--panel-bg);min-width:0;padding:18px}.jobs-detail-header{justify-content:space-between;align-items:flex-start;gap:12px;margin-bottom:16px;display:flex}.jobs-detail-header h4{margin:4px 0 0;font-size:1.15rem}.jobs-detail-stack,.jobs-runtime-list{gap:14px;display:grid}.jobs-runtime-row{border:1px solid var(--line);border-radius:var(--radius-md);background:var(--panel-muted);gap:4px;padding:10px 12px;display:grid}.jobs-runtime-row strong,.jobs-runtime-row small{overflow-wrap:anywhere;word-break:break-word;margin:0}.jobs-runtime-row small{color:var(--muted)}.code-editor{color:#e2e8f0;background:#0f172a;border-color:#334155;min-height:540px}@media (width<=1080px){.app-frame,.metric-grid,.two-column-grid,.usage-grid,.field-grid,.config-grid,.key-value-grid{grid-template-columns:1fr}.sidebar{border-right:none;border-bottom:1px solid var(--line)}.jobs-board-layout{grid-template-columns:1fr}.jobs-columns{border-right:none;border-bottom:1px solid var(--line)}}@media (width<=780px){.main-panel,.sidebar,.panel,.login-card{padding:18px}.topbar,.page-header{flex-direction:column}.topbar-actions{justify-items:stretch;width:100%}.view-switch{width:100%}.view-switch-link{flex:1 1 0;justify-content:center}.jobs-header-search{min-width:0}.terminal-shell,.terminal-host{min-height:60vh}}