@slopus/happy-terminal 0.3.0-beta.13

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 (248) hide show
  1. package/LICENSE +21 -0
  2. package/LICENSE-CODEX +203 -0
  3. package/LICENSE-GROK-BUILD +204 -0
  4. package/LICENSE-HAPPY +21 -0
  5. package/README.md +60 -0
  6. package/THIRD-PARTY-NOTICES.md +34 -0
  7. package/dist/HappyTerminalUserError.d.ts +12 -0
  8. package/dist/app/AppTranscriptEntry.d.ts +33 -0
  9. package/dist/app/AppendOnlyStreamingRender.d.ts +12 -0
  10. package/dist/app/CodexFileDiff.d.ts +20 -0
  11. package/dist/app/CodexMcpToolCall.d.ts +25 -0
  12. package/dist/app/CodingAssistantAgentBackend.d.ts +81 -0
  13. package/dist/app/CodingAssistantApp.d.ts +128 -0
  14. package/dist/app/CompletedTurn.d.ts +11 -0
  15. package/dist/app/FileMentionAutocomplete.d.ts +30 -0
  16. package/dist/app/HappyTerminalProcessTerminal.d.ts +7 -0
  17. package/dist/app/NoticeChild.d.ts +4 -0
  18. package/dist/app/SecretMenuController.d.ts +31 -0
  19. package/dist/app/SelectionList.d.ts +24 -0
  20. package/dist/app/SessionDraftSync.d.ts +51 -0
  21. package/dist/app/StartupStatusApp.d.ts +34 -0
  22. package/dist/app/StartupStatusCardModel.d.ts +22 -0
  23. package/dist/app/TemporaryFullscreenController.d.ts +9 -0
  24. package/dist/app/TerminalColorLevel.d.ts +1 -0
  25. package/dist/app/TerminalOutputTrace.d.ts +12 -0
  26. package/dist/app/TerminalTheme.d.ts +11 -0
  27. package/dist/app/TranscriptEntryRenderCache.d.ts +10 -0
  28. package/dist/app/applyWorkflowRunUpdate.d.ts +2 -0
  29. package/dist/app/blendComposerBackground.d.ts +2 -0
  30. package/dist/app/boundedJsonStringify.d.ts +1 -0
  31. package/dist/app/calculateCacheHitPercent.d.ts +2 -0
  32. package/dist/app/codexDiffAnsi.d.ts +17 -0
  33. package/dist/app/compactCompletedTurnEntries.d.ts +2 -0
  34. package/dist/app/containsMarkdownTable.d.ts +1 -0
  35. package/dist/app/createAgentMarkdownTheme.d.ts +3 -0
  36. package/dist/app/createBackgroundTerminalViewer.d.ts +16 -0
  37. package/dist/app/createCompletedTurn.d.ts +6 -0
  38. package/dist/app/createEditorTheme.d.ts +3 -0
  39. package/dist/app/createFileMentionAutocompleteItems.d.ts +3 -0
  40. package/dist/app/createSecretInputPanel.d.ts +12 -0
  41. package/dist/app/createSelectionPanel.d.ts +14 -0
  42. package/dist/app/createSerialTaskQueue.d.ts +1 -0
  43. package/dist/app/createSessionPicker.d.ts +17 -0
  44. package/dist/app/createSlashCommands.d.ts +7 -0
  45. package/dist/app/createStopOnceHandler.d.ts +1 -0
  46. package/dist/app/createSubagentMonitor.d.ts +17 -0
  47. package/dist/app/createTerminalInputBurstHandler.d.ts +5 -0
  48. package/dist/app/createWorkflowMonitor.d.ts +15 -0
  49. package/dist/app/defaultTerminalTheme.d.ts +1 -0
  50. package/dist/app/describeModelChoice.d.ts +4 -0
  51. package/dist/app/describeProviderSignIn.d.ts +2 -0
  52. package/dist/app/describeReasoningLevel.d.ts +4 -0
  53. package/dist/app/detectCodexDiffLanguage.d.ts +1 -0
  54. package/dist/app/encodeModelChoice.d.ts +1 -0
  55. package/dist/app/endsAfterOpeningCodeFence.d.ts +1 -0
  56. package/dist/app/findFileMentionContext.d.ts +9 -0
  57. package/dist/app/findFileMentionPrefix.d.ts +5 -0
  58. package/dist/app/formatActivityElapsedTime.d.ts +1 -0
  59. package/dist/app/formatCodexMcpToolResult.d.ts +3 -0
  60. package/dist/app/formatCompactTokens.d.ts +1 -0
  61. package/dist/app/formatFileMention.d.ts +1 -0
  62. package/dist/app/formatProviderError.d.ts +6 -0
  63. package/dist/app/formatRelativeTime.d.ts +2 -0
  64. package/dist/app/formatResetDuration.d.ts +1 -0
  65. package/dist/app/formatSessionPickerEntry.d.ts +14 -0
  66. package/dist/app/formatSessionTokenStatus.d.ts +6 -0
  67. package/dist/app/formatSessionUsageSummary.d.ts +3 -0
  68. package/dist/app/formatStartupStatusUsageRemaining.d.ts +2 -0
  69. package/dist/app/formatStartupStatusUsageRows.d.ts +2 -0
  70. package/dist/app/formatSubagentToolCall.d.ts +10 -0
  71. package/dist/app/formatToolPermissionNotice.d.ts +3 -0
  72. package/dist/app/formatToolResultForDisplay.d.ts +2 -0
  73. package/dist/app/formatTurnUsageSummary.d.ts +2 -0
  74. package/dist/app/formatWorkUsageSummary.d.ts +14 -0
  75. package/dist/app/highlightAgentCode.d.ts +1 -0
  76. package/dist/app/highlightCodexDiffLine.d.ts +2 -0
  77. package/dist/app/highlightShellCommand.d.ts +1 -0
  78. package/dist/app/humanizeGoalStatus.d.ts +2 -0
  79. package/dist/app/humanizeMcpName.d.ts +1 -0
  80. package/dist/app/humanizePermissionMode.d.ts +2 -0
  81. package/dist/app/humanizePermissionReviewLevel.d.ts +2 -0
  82. package/dist/app/humanizeProviderId.d.ts +1 -0
  83. package/dist/app/humanizeReasoningLevel.d.ts +1 -0
  84. package/dist/app/humanizeSubagentStatus.d.ts +2 -0
  85. package/dist/app/humanizeToolName.d.ts +1 -0
  86. package/dist/app/humanizeWorkflowStatus.d.ts +2 -0
  87. package/dist/app/installResumeInstructions.d.ts +26 -0
  88. package/dist/app/installTerminalCrashCleanup.d.ts +26 -0
  89. package/dist/app/isLightTerminalBackground.d.ts +2 -0
  90. package/dist/app/layoutCodexFileDiff.d.ts +13 -0
  91. package/dist/app/looksLikeAuthenticationFailure.d.ts +5 -0
  92. package/dist/app/nearestXtermColorIndex.d.ts +2 -0
  93. package/dist/app/parseCodexMcpToolInvocation.d.ts +2 -0
  94. package/dist/app/parseSessionCommand.d.ts +6 -0
  95. package/dist/app/providerErrorResetAt.d.ts +2 -0
  96. package/dist/app/providerQuotaToStartupStatusUsage.d.ts +3 -0
  97. package/dist/app/readClipboardImage.d.ts +9 -0
  98. package/dist/app/renderActivityWave.d.ts +3 -0
  99. package/dist/app/renderAgentMarkdown.d.ts +8 -0
  100. package/dist/app/renderBackgroundTerminalCompletion.d.ts +1 -0
  101. package/dist/app/renderBackgroundTerminalInteraction.d.ts +2 -0
  102. package/dist/app/renderBackgroundTerminalSummary.d.ts +1 -0
  103. package/dist/app/renderChildRows.d.ts +13 -0
  104. package/dist/app/renderCodexDiffLine.d.ts +3 -0
  105. package/dist/app/renderCodexFileDiff.d.ts +7 -0
  106. package/dist/app/renderCodexMcpToolCall.d.ts +2 -0
  107. package/dist/app/renderCompletedTurnStats.d.ts +2 -0
  108. package/dist/app/renderExecCommand.d.ts +11 -0
  109. package/dist/app/renderExploration.d.ts +9 -0
  110. package/dist/app/renderFullscreenComponent.d.ts +8 -0
  111. package/dist/app/renderHappyTerminalBanner.d.ts +6 -0
  112. package/dist/app/renderHappyTerminalVersion.d.ts +1 -0
  113. package/dist/app/renderNoticeWithChildren.d.ts +7 -0
  114. package/dist/app/renderPendingSteeringMessages.d.ts +1 -0
  115. package/dist/app/renderStartupStatusCard.d.ts +7 -0
  116. package/dist/app/renderSubagentSummary.d.ts +6 -0
  117. package/dist/app/renderTurnCompletionSeparator.d.ts +1 -0
  118. package/dist/app/renderWorkflowSummary.d.ts +1 -0
  119. package/dist/app/resolveInputBackground.d.ts +3 -0
  120. package/dist/app/resolveStartupProviderQuota.d.ts +3 -0
  121. package/dist/app/resolveStartupSessionId.d.ts +18 -0
  122. package/dist/app/resolveTerminalColorLevel.d.ts +2 -0
  123. package/dist/app/resolveTerminalStyle.d.ts +1 -0
  124. package/dist/app/resolveTerminalTheme.d.ts +5 -0
  125. package/dist/app/runApp.d.ts +27 -0
  126. package/dist/app/runClipboardCommand.d.ts +8 -0
  127. package/dist/app/sanitizeTerminalText.d.ts +1 -0
  128. package/dist/app/shortenHomePath.d.ts +2 -0
  129. package/dist/app/sortSubagentsForDisplay.d.ts +2 -0
  130. package/dist/app/subagentElapsedMs.d.ts +2 -0
  131. package/dist/app/subagentLogMessageText.d.ts +2 -0
  132. package/dist/app/surfaceThemedLine.d.ts +3 -0
  133. package/dist/app/truncatePathToWidth.d.ts +1 -0
  134. package/dist/app/truncateTextForDisplay.d.ts +5 -0
  135. package/dist/app/truncateUtf8BytesForDisplay.d.ts +1 -0
  136. package/dist/app/upsertSubagentSummary.d.ts +2 -0
  137. package/dist/app/workflowDisplay.d.ts +2 -0
  138. package/dist/client/HappyAgentEventHub.d.ts +25 -0
  139. package/dist/client/RemoteAgent.d.ts +74 -0
  140. package/dist/client/RemoteAgentRunError.d.ts +4 -0
  141. package/dist/client/RemoteTerminalAttachment.d.ts +19 -0
  142. package/dist/client/RemoteTerminalClientReplica.d.ts +14 -0
  143. package/dist/client/ensureLocalProtocolServer.d.ts +10 -0
  144. package/dist/client/fetchProviderQuotas.d.ts +10 -0
  145. package/dist/client/index.d.ts +8 -0
  146. package/dist/client/loadAgentCatalog.d.ts +32 -0
  147. package/dist/config/createProjectConfigSecurityNotice.d.ts +10 -0
  148. package/dist/config/defaultConfig.d.ts +2 -0
  149. package/dist/config/getDefaultGlobalConfigPath.d.ts +1 -0
  150. package/dist/config/getDefaultLocalConfigPath.d.ts +1 -0
  151. package/dist/config/getDefaultRuntimeConfigPath.d.ts +1 -0
  152. package/dist/config/getHappyConfigDirectory.d.ts +1 -0
  153. package/dist/config/getHappyTerminalHome.d.ts +1 -0
  154. package/dist/config/index.d.ts +15 -0
  155. package/dist/config/loadConfig.d.ts +2 -0
  156. package/dist/config/mergeConfigValues.d.ts +2 -0
  157. package/dist/config/parseConfigToml.d.ts +7 -0
  158. package/dist/config/readConfigFile.d.ts +2 -0
  159. package/dist/config/readProjectConfigFile.d.ts +2 -0
  160. package/dist/config/resolveConfigPaths.d.ts +2 -0
  161. package/dist/config/runtimeConfigLock.d.ts +1 -0
  162. package/dist/config/types.d.ts +74 -0
  163. package/dist/config/updateRuntimeConfig.d.ts +2 -0
  164. package/dist/config/updateRuntimePreferences.d.ts +2 -0
  165. package/dist/config/withoutProjectMachineSettings.d.ts +7 -0
  166. package/dist/config/writeRuntimeConfig.d.ts +3 -0
  167. package/dist/config/writeRuntimeConfigDefaults.d.ts +2 -0
  168. package/dist/daemon/createUnixSocketFetch.d.ts +2 -0
  169. package/dist/daemon/daemonPid.d.ts +11 -0
  170. package/dist/daemon/ensureHappyAgentBinary.d.ts +15 -0
  171. package/dist/daemon/ensureLocalProtocolServer.d.ts +24 -0
  172. package/dist/daemon/getHappyDaemonPaths.d.ts +16 -0
  173. package/dist/daemon/happyAgentBinaryConfig.d.ts +15 -0
  174. package/dist/daemon/index.d.ts +5 -0
  175. package/dist/daemon/runDaemonCommand.d.ts +4 -0
  176. package/dist/debug/DebugLog.d.ts +11 -0
  177. package/dist/debug/closeNodeInspector.d.ts +1 -0
  178. package/dist/debug/createDebugJsonReplacer.d.ts +1 -0
  179. package/dist/debug/createRequestDebugDirectory.d.ts +1 -0
  180. package/dist/debug/getDebugRootDirectory.d.ts +1 -0
  181. package/dist/debug/getNodeInspectorUrl.d.ts +1 -0
  182. package/dist/debug/index.d.ts +8 -0
  183. package/dist/debug/openNodeInspector.d.ts +1 -0
  184. package/dist/debug/registerHappyTerminalDebugRoot.d.ts +5 -0
  185. package/dist/docs/DESIGN.md +2191 -0
  186. package/dist/docs/README.md +93 -0
  187. package/dist/docs/agents-and-collaboration.md +365 -0
  188. package/dist/docs/architecture.md +468 -0
  189. package/dist/docs/extending.md +561 -0
  190. package/dist/docs/happy.md +386 -0
  191. package/dist/docs/permissions-and-sandbox.md +342 -0
  192. package/dist/docs/workspaces.md +281 -0
  193. package/dist/errorToMessage.d.ts +1 -0
  194. package/dist/formatCliFailure.d.ts +10 -0
  195. package/dist/index.d.ts +3 -0
  196. package/dist/index.js +17151 -0
  197. package/dist/main.js +18946 -0
  198. package/dist/observability/daemonContext.d.ts +16 -0
  199. package/dist/observability/index.d.ts +1 -0
  200. package/dist/processes/BoundedOutputBuffer.d.ts +20 -0
  201. package/dist/processes/NativeProcessManager.d.ts +66 -0
  202. package/dist/processes/ProcessGroupReaper.d.ts +32 -0
  203. package/dist/processes/index.d.ts +7 -0
  204. package/dist/processes/isProcessRunning.d.ts +1 -0
  205. package/dist/processes/isTargetProcessAlive.d.ts +1 -0
  206. package/dist/processes/killProcessTree.d.ts +2 -0
  207. package/dist/processes/resolveSystemShell.d.ts +1 -0
  208. package/dist/processes/startProcessTransport.d.ts +33 -0
  209. package/dist/processes/types.d.ts +41 -0
  210. package/dist/processes/waitForProcessExit.d.ts +2 -0
  211. package/dist/protocol/AppletProtocol.d.ts +101 -0
  212. package/dist/protocol/Attachment.d.ts +96 -0
  213. package/dist/protocol/ClientProtocolTypes.d.ts +481 -0
  214. package/dist/protocol/DocumentProtocol.d.ts +109 -0
  215. package/dist/protocol/EventId.d.ts +1 -0
  216. package/dist/protocol/FolderProtocol.d.ts +236 -0
  217. package/dist/protocol/FolderSharingProtocol.d.ts +97 -0
  218. package/dist/protocol/GitHubPluginProtocol.d.ts +43 -0
  219. package/dist/protocol/GlobalSecurityProtocol.d.ts +7 -0
  220. package/dist/protocol/HappyCloudProtocol.d.ts +178 -0
  221. package/dist/protocol/InstallationProtocol.d.ts +80 -0
  222. package/dist/protocol/OnboardingProtocol.d.ts +47 -0
  223. package/dist/protocol/P2pCredentialProtocol.d.ts +273 -0
  224. package/dist/protocol/P2pIdentityProtocol.d.ts +8 -0
  225. package/dist/protocol/P2pPairingProtocol.d.ts +68 -0
  226. package/dist/protocol/P2pProtocol.d.ts +185 -0
  227. package/dist/protocol/PluginWireTypes.d.ts +81 -0
  228. package/dist/protocol/ProfileProtocol.d.ts +127 -0
  229. package/dist/protocol/ProjectFileProtocol.d.ts +63 -0
  230. package/dist/protocol/ProjectProtocol.d.ts +646 -0
  231. package/dist/protocol/ProtocolVersion.d.ts +8 -0
  232. package/dist/protocol/ServiceNotice.d.ts +175 -0
  233. package/dist/protocol/SessionProtocol.d.ts +1156 -0
  234. package/dist/protocol/SharingProtocol.d.ts +159 -0
  235. package/dist/protocol/SlotProtocol.d.ts +270 -0
  236. package/dist/protocol/TimelineProtocol.d.ts +88 -0
  237. package/dist/protocol/WorkletProtocol.d.ts +159 -0
  238. package/dist/protocol/createEventIdFactory.d.ts +7 -0
  239. package/dist/protocol/index.d.ts +34 -0
  240. package/dist/readPackageVersion.d.ts +1 -0
  241. package/dist/readPackageVersion.js +16 -0
  242. package/dist/reportCliFailure.d.ts +2 -0
  243. package/dist/runHappyTerminal.d.ts +6 -0
  244. package/dist/terminal/index.d.ts +2 -0
  245. package/dist/terminal/types.d.ts +39 -0
  246. package/dist/types.d.ts +6 -0
  247. package/dist/writeStderrSync.d.ts +5 -0
  248. package/package.json +97 -0
@@ -0,0 +1,561 @@
1
+ # Extending Happy Agent
2
+
3
+ This guide is written for a coding agent running inside Happy Agent that has been asked
4
+ to extend Happy Agent. Everything below describes behavior that actually ships; where
5
+ something is planned rather than implemented, it says so explicitly.
6
+
7
+ There are five extension surfaces, ordered by how much they let you change:
8
+
9
+ | Surface | What it adds | Who writes it |
10
+ | -------------------------------------- | --------------------------------------------------------------------------------------- | ----------------------- |
11
+ | **Plugins** | A JavaScript or TypeScript process that contributes MCP tools and local UI applications | You, inside Happy Agent |
12
+ | **Skills** | Instructions a model loads on demand from a `SKILL.md` file | You or the user |
13
+ | **MCP servers** | Tools, resources, and prompts from an external process or HTTP service | The user, in config |
14
+ | **Happy Agent Connect / integrations** | External apps that read Happy Agent's live state and drive it | An application author |
15
+ | **Subagents and workflows** | Extra agents and deterministic multi-agent scripts, at runtime | You, per task |
16
+
17
+ ---
18
+
19
+ ## Plugins
20
+
21
+ A local plugin is the general-purpose extension mechanism. It is ready-to-run
22
+ JavaScript or TypeScript that Happy Agent runs as its own sandboxed process, connected
23
+ back to the daemon over a private Unix socket. From there it can create
24
+ workspaces, send messages to agents, read provider usage, contribute MCP tools,
25
+ and contribute a small local UI application.
26
+
27
+ ### What a plugin folder contains
28
+
29
+ Three files are enough. Happy Agent does not require a `package.json`.
30
+
31
+ ```text
32
+ project-counter/
33
+ ├── happy.plugin.json manifest — required
34
+ ├── icon.png PNG icon — required
35
+ └── index.ts main entry point — required
36
+ ```
37
+
38
+ ### The manifest
39
+
40
+ `happy.plugin.json` is validated against a strict schema and **extra fields are
41
+ rejected**:
42
+
43
+ ```json
44
+ {
45
+ "name": "Project Counter",
46
+ "author": "Acme Tools",
47
+ "category": "developer-tools",
48
+ "description": "Reports how many projects Happy Agent knows about.",
49
+ "main": "index.ts",
50
+ "icon": "icon.png"
51
+ }
52
+ ```
53
+
54
+ | Field | Rule |
55
+ | ------------- | ------------------------------------------------------------------------------------------------------------ |
56
+ | `name` | Non-empty string. Human-readable; also used to derive the agent-facing MCP tool name. |
57
+ | `author` | Required 1–80 character publisher label without leading/trailing whitespace or control/direction characters. |
58
+ | `category` | Required catalog category; see the canonical values below. |
59
+ | `description` | Required 1–512 character explanation of what the plugin does. |
60
+ | `main` | Process entry path; optional only when skills or a system prompt provide the plugin's behavior. |
61
+ | `icon` | Relative path ending in `.png` (any capitalization of the extension). |
62
+ | `version` | Optional Semantic Versioning string; an omission becomes `0.0.0`. |
63
+ | `apps` | Optional list of bounded static MCP App manifests. |
64
+
65
+ `category` is exactly one of `automation`, `collaboration`, `data`,
66
+ `developer-tools`, `media`, `productivity`, `utilities`, or `other`.
67
+
68
+ Additional rules Happy Agent enforces when it reads the manifest:
69
+
70
+ - `main` and `icon` must be relative and must resolve **inside** the plugin
71
+ folder.
72
+ - Both must resolve to ordinary files inside the plugin's real directory tree;
73
+ final or intermediate symbolic-link escapes are rejected.
74
+ - The icon must be a fully decodable square PNG, between 1×1 and 2048×2048
75
+ pixels and no larger than 4 MiB. A renamed JPEG, truncated PNG, SVG,
76
+ placeholder string, or URL is rejected and the plugin does not register.
77
+
78
+ Do not invent manifest fields such as `permissions` or `contributes`; adding one
79
+ makes the manifest invalid.
80
+
81
+ ### The icon
82
+
83
+ Every registered plugin must ship an original PNG icon. Happy Agent bundles a skill for
84
+ producing one, `local-plugin-icon`.
85
+ It triggers automatically when you create or edit a plugin, a `happy.plugin.json`,
86
+ or its icon. Follow it: it defines the shared visual family (Jobs-era iPhone icon
87
+ craft, one metaphor, no text or third-party marks) and the verification steps —
88
+ generate a square image, prefer 1024×1024, inspect it, save a real PNG in the
89
+ plugin folder, keep it at or below 2048×2048 and 4 MiB, and point `icon` at that
90
+ relative path.
91
+
92
+ ### The entry file
93
+
94
+ Happy Agent starts `main` with the same Node executable that runs Happy Agent. Node strips
95
+ erasable TypeScript syntax without a compile step or extra flag, so TypeScript
96
+ may use top-level `await` and relative `.ts` imports. Constructs that require
97
+ JavaScript generation are not supported. Use `.mjs` or a local
98
+ `"type": "module"` package declaration for JavaScript ESM.
99
+
100
+ ```ts
101
+ import { happy } from "happy-plugins";
102
+
103
+ const projects = await happy.projects.list();
104
+ console.log(`Happy Agent has ${projects.length} projects.`);
105
+
106
+ await happy.ready("Ready.");
107
+
108
+ // A service-style plugin stays alive until Happy Agent shuts it down.
109
+ await new Promise<void>((resolve) => {
110
+ process.once("SIGTERM", resolve);
111
+ process.once("SIGINT", resolve);
112
+ });
113
+ ```
114
+
115
+ Plugin code never opens a connection, finds credentials, or speaks Happy Agent's
116
+ protocol. The `happy` singleton reads the socket path and token that the daemon
117
+ injects and connects for you. Happy Agent registers one ESM loader hook with `--import`
118
+ to map `happy-plugins` and `happy-plugins/internal` to the SDK shipped with Happy Agent;
119
+ the plugin does not vendor a runtime SDK.
120
+
121
+ Happy Agent provides only `happy-plugins` at runtime. Bundle every other third-party
122
+ dependency into the plugin's own files; Happy Agent does not copy `node_modules` when
123
+ it installs a plugin.
124
+
125
+ ### The SDK surface
126
+
127
+ All SDK methods return promises; inputs and daemon responses are validated with
128
+ TypeBox at runtime. The current surface is:
129
+
130
+ ```ts
131
+ happy.projects.list();
132
+
133
+ happy.workspaces.list({ projectId? });
134
+ happy.workspaces.create({ projectId, name, baseRef? });
135
+ happy.workspaces.rename({ projectId, workspaceId, name, version });
136
+ happy.workspaces.archive({ projectId, workspaceId, version });
137
+
138
+ happy.sessions.list();
139
+ happy.sessions.create({ cwd, providerId?, modelId?, effort?, appendSystemPrompt?, workspaceId? });
140
+
141
+ happy.agents.sendMessage({ agentId, message });
142
+
143
+ happy.providers.usage();
144
+
145
+ happy.mcp.startServer({ name, tools });
146
+ happy.ready("Ready."); // Call once, after every startup contribution is registered.
147
+ happy.ui.startApplication({ id, title, entry, navigation?, resources, actions });
148
+ ```
149
+
150
+ Workspace mutations are optimistic: pass the `version` from the most recently
151
+ returned workspace. Failed requests throw `HappyPluginApiError` carrying the HTTP
152
+ status.
153
+
154
+ #### Contributing MCP tools
155
+
156
+ This is the first and most useful plugin point. No MCP server package is needed —
157
+ reuse the `Type` and `defineMcpTool` exports:
158
+
159
+ ```ts
160
+ import { defineMcpTool, happy, Type } from "happy-plugins";
161
+
162
+ await happy.mcp.startServer({
163
+ name: "Catalog",
164
+ tools: [
165
+ defineMcpTool({
166
+ name: "list_projects",
167
+ description: "List every local Happy Agent project.",
168
+ inputSchema: Type.Object({}, { additionalProperties: false }),
169
+ async execute(_input, { signal }) {
170
+ signal.throwIfAborted();
171
+ const projects = await happy.projects.list();
172
+ return { content: [{ type: "text", text: JSON.stringify(projects) }] };
173
+ },
174
+ }),
175
+ ],
176
+ });
177
+ await happy.ready("Ready.");
178
+
179
+ // Keep the process alive so the server stays registered.
180
+ await new Promise<void>(() => {});
181
+ ```
182
+
183
+ Happy Agent offers the tool in ordinary sessions everywhere. The agent-facing name is
184
+ stable and derived from the plugin name, server name, and tool name by the SDK's
185
+ `createHappyMcpToolName`:
186
+
187
+ ```text
188
+ mcp__<plugin name>_·_<server name>__<tool name> with every character outside
189
+ [A-Za-z0-9_-] replaced by "_"
190
+ ```
191
+
192
+ For the example above with a plugin named `Project Tools`, that is
193
+ `mcp__Project_Tools___Catalog__list_projects`. Call
194
+ `createHappyMcpToolName(pluginName, serverName, toolName)` rather than
195
+ hand-writing it in a test.
196
+
197
+ Plugin tool calls use the same permission path as configured MCP servers: they
198
+ require Auto or Full access, and every Auto call is reviewed, because a plugin
199
+ may act outside Happy Agent's filesystem sandbox. Cancellation reaches the handler's
200
+ `AbortSignal`, and disconnected, replaced, restarted, or uninstalled generations
201
+ are retired immediately.
202
+
203
+ #### Contributing a local application
204
+
205
+ A plugin may register one or more static bundles plus typed actions through
206
+ `happy.ui.startApplication`. Happy Agent serves them to hosts (currently the Happy2
207
+ Electron shell) which mount them instantly. Limits enforced by the daemon: 8
208
+ applications per plugin, 32 actions and 64 resources per application, 256 KiB per
209
+ resource, 1 MiB per decoded bundle, 64 concurrent actions, a 30-second action
210
+ timeout, and 1 MiB action bodies. Supported media types are JSON, WOFF2, JPEG,
211
+ PNG, SVG, WebP, CSS, HTML, and JavaScript.
212
+
213
+ ### Where things live
214
+
215
+ Plugin code and Happy Agent's bounded log stay in Happy Agent's managed home; everything the
216
+ plugin writes at runtime goes to a folder a person can open.
217
+
218
+ ```text
219
+ ~/.happy/agent/plugins/<folder>/ installed code, managed by Happy Agent
220
+ ├── happy.plugin.json
221
+ ├── icon.png
222
+ ├── index.ts
223
+ └── plugin.log bounded current-run output
224
+
225
+ ~/Happy/Plugins/<folder>/ the plugin's writable folder (macOS)
226
+ ~/happy/plugins/<folder>/ the same on Linux
227
+ └── .runtime/plugin.sock per-plugin API socket
228
+ ```
229
+
230
+ `<folder>` is derived from the source directory's base name, lowercased with
231
+ runs of unsupported characters replaced by `-`.
232
+
233
+ Overrides, all requiring absolute paths:
234
+
235
+ | Variable | Effect |
236
+ | ----------------------------- | ------------------------------------------ |
237
+ | `HAPPY_HOME_DIR` | Moves Happy Agent's private `.happy` root. |
238
+ | `HAPPY_PLUGINS_DIRECTORY` | Moves the installed-plugin root. |
239
+ | `HAPPY_PLUGIN_DATA_DIRECTORY` | Moves the writable plugin-data root. |
240
+
241
+ The plugin process runs with its writable folder as the working directory, under
242
+ Happy Agent's existing command sandbox confined to that folder. Happy Agent injects:
243
+
244
+ | Variable | Meaning |
245
+ | -------------------------- | ---------------------------------------------- |
246
+ | `HAPPY_PLUGIN_DIRECTORY` | Absolute path to the plugin's writable folder. |
247
+ | `HAPPY_PLUGIN_SOCKET_PATH` | Private Unix socket used by the SDK. |
248
+ | `HAPPY_PLUGIN_TOKEN` | Per-process bearer token used by the SDK. |
249
+
250
+ Write state in `HAPPY_PLUGIN_DIRECTORY` and nowhere else.
251
+
252
+ ### Installing, listing, logging, uninstalling
253
+
254
+ Four agent tools drive the lifecycle:
255
+
256
+ | Tool | Arguments | What it does |
257
+ | ------------------ | ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
258
+ | `plugin_install` | `path` — folder containing `happy.plugin.json` | Copies and validates the ready-to-run folder, then starts the plugin before returning. |
259
+ | `plugin_list` | none | Returns every installed plugin with `status`, `directory`, `dataDirectory`, `logAvailable`, plus registration `failures`. |
260
+ | `plugin_logs` | `name` — plugin name or folder name | Returns the newest bounded log or startup diagnostic with `status`, `source` (`current_run` or `error`), and `truncated`. |
261
+ | `plugin_uninstall` | `name` | Stops the plugin, removes its installed code, and keeps its writable folder. |
262
+
263
+ Plugins live outside the workspace, so all four are reviewed in Auto mode;
264
+ `plugin_install` and `plugin_uninstall` additionally run with a temporary Full
265
+ access override because they must write outside the sandbox. A denial is a real
266
+ answer: do not retry the same action by another route.
267
+
268
+ Installation is staged. The plugin is copied into a hidden folder and its
269
+ manifest, icon, and main entry point are validated there. An invalid plugin is
270
+ never installed and never replaces a working one. `.git`, `.runtime`,
271
+ `node_modules`, and `plugin.log` are excluded from the copy, and the copy is
272
+ bounded to 2,000 files and 32 MiB. Happy Agent provides `happy-plugins` at runtime; all
273
+ other third-party dependencies must be bundled into the plugin's own files.
274
+
275
+ Every change publishes a live `plugins_changed` event carrying the whole current
276
+ set, so clients never poll and never wait for a daemon restart. The daemon also loads every installed plugin at startup. A
277
+ plugin's authoritative state is one of `running`, `stopped`, or `failed`.
278
+
279
+ For the user, `/plugins` shows the installed set and `/plugins <name>` prints
280
+ that plugin's current log.
281
+
282
+ ### Minimal walkthrough
283
+
284
+ Building a plugin from inside Happy Agent, end to end:
285
+
286
+ 1. Create the folder — `.context/project-counter/` is a good scratch location, or
287
+ somewhere the user names.
288
+ 2. Write `happy.plugin.json` with the six fields this process plugin needs:
289
+ `name`, `author`, `category`, `description`, `main`, and `icon`.
290
+ 3. Write `index.ts` against the `happy` singleton.
291
+ 4. Generate `icon.png` using the bundled `local-plugin-icon` skill; verify it is
292
+ a fully decodable square PNG no larger than 2048×2048 pixels or 4 MiB.
293
+ 5. Type-check and test the plugin, then call `plugin_install` with the absolute
294
+ path to the folder. Happy Agent validates, copies, and starts it without compiling.
295
+ 6. Call `plugin_list` to confirm `status: "running"`, and `plugin_logs` if it is
296
+ `failed` or `stopped` — startup diagnostics come back through the same tool.
297
+ 7. If it contributes MCP tools, they become available to sessions under the
298
+ `mcp__…` name above.
299
+
300
+ To iterate without installing, the SDK ships a runner that starts a source plugin
301
+ against an in-memory fake host, prints every request and registration, lists MCP
302
+ tools, and can call one. It needs Node 22.6 or newer and no Docker:
303
+
304
+ ```sh
305
+ pnpm happy-plugin dev ./index.ts \
306
+ --seed ./happy.plugin.dev.json \
307
+ --list-tools \
308
+ --call "Project tools/list_projects" \
309
+ --arguments '{}'
310
+ ```
311
+
312
+ `createHappyPluginTestHost()` exposes the same host programmatically for tests,
313
+ including `host.mcp.*`, `host.ui.*`, and a real `HAPPY_PLUGIN_DIRECTORY`.
314
+
315
+ For end-to-end coverage, write a gym test instead of mocking the daemon: drive a
316
+ real plugin through its sandbox socket, and assert that a source plugin's MCP
317
+ tool reaches an active session.
318
+
319
+ ### Trust
320
+
321
+ Happy Agent does not implement a permission model for plugins. Plugin code is relatively
322
+ trusted and is not restricted by per-capability checks. What _is_ enforced is the
323
+ process sandbox, the writable-folder confinement, the authenticated socket, and
324
+ the ordinary MCP review path for tools a plugin contributes to a session.
325
+
326
+ ---
327
+
328
+ ## Skills
329
+
330
+ A skill is a set of instructions delivered through a `SKILL.md` file. It changes
331
+ what a model knows how to do without changing any code. Happy Agent follows Codex
332
+ behavior and scope here deliberately; it does not implement Claude Code's
333
+ expanded skill runtime, and it does not interpret Claude or Pi skill trees.
334
+
335
+ ### Where skills are discovered
336
+
337
+ Happy Agent searches these roots, in this order:
338
+
339
+ 1. **Builtin** — skills shipped inside Happy Agent (currently `local-plugin-icon`).
340
+ Read-only; never write here.
341
+ 2. **User** — `~/.codex/skills` and `~/.agents/skills`.
342
+ 3. **Project** — `.agents/skills` in every directory from the project root down
343
+ to the working directory.
344
+
345
+ Within each root, discovery walks directories recursively looking for a
346
+ `SKILL.md`; finding one stops descent into that subtree. Entries starting with
347
+ `.` and `node_modules` are skipped. Later roots win on name collision, so a
348
+ project skill overrides a user skill of the same name, which overrides a builtin.
349
+
350
+ ### `SKILL.md` format
351
+
352
+ YAML frontmatter followed by markdown instructions:
353
+
354
+ ```markdown
355
+ ---
356
+ name: release-notes
357
+ description: Use when the user asks to draft release notes from merged pull requests.
358
+ ---
359
+
360
+ # Release notes
361
+
362
+ 1. Collect merged PRs since the last tag.
363
+ 2. Group them by area.
364
+ ...
365
+ ```
366
+
367
+ Only three frontmatter keys are read:
368
+ `name` (string), `description` (string), and `disable-model-invocation`
369
+ (boolean). The first two are what matter — `disable-model-invocation` is parsed
370
+ but nothing currently consumes it. Any other key is ignored.
371
+
372
+ Validation, when a skill file is loaded:
373
+
374
+ - `name` defaults to the containing folder's name when frontmatter omits it, and
375
+ must match `^[a-z0-9-]+$`, be at most 64 characters, and not start or end with
376
+ `-` or contain `--`.
377
+ - `description` is required (there is no fallback), is trimmed, and must be
378
+ 1–1024 characters.
379
+ - A file failing either check is silently skipped, so a skill that does not
380
+ appear almost always has an invalid name or a missing description.
381
+
382
+ ### When a skill triggers
383
+
384
+ Happy Agent injects the catalog — name, description, and location — into the system
385
+ prompt. The model uses a skill when the user names it or the task clearly matches
386
+ its description, reads the complete file before acting, and resolves relative
387
+ paths in the skill against the directory containing that `SKILL.md`.
388
+
389
+ Skill files are **instruction resources only**. Frontmatter that requests hooks,
390
+ shell execution, model switching, or permission changes is ignored by design; do
391
+ not add such fields expecting them to work.
392
+
393
+ ## MCP servers
394
+
395
+ MCP is how Happy Agent consumes tools it did not write. Servers are configured in TOML,
396
+ not installed.
397
+
398
+ ### Configuration
399
+
400
+ Config layers, resolved in this order:
401
+
402
+ | Source | File |
403
+ | --------- | ------------------------------------------------------------------------------------------------------- |
404
+ | `global` | `happy.toml` in Happy Agent's config directory — `~/Happy/Config` on macOS or `~/happy/config` on Linux |
405
+ | `runtime` | `~/.happy/agent/runtime.toml` |
406
+ | `project` | `happy.toml` in the project |
407
+
408
+ Global and runtime are trusted layers. Project entries are separate: a project
409
+ server with the same name as a trusted one does not override it — the trusted one
410
+ wins and is flagged `projectShadowed`.
411
+
412
+ A local stdio server:
413
+
414
+ ```toml
415
+ [mcp_servers.docs]
416
+ command = "docs-mcp-server"
417
+ args = ["--stdio"]
418
+ env = { API_TOKEN = "token" }
419
+ cwd = "/absolute/working/directory"
420
+ enabled = true
421
+ startup_timeout_sec = 10
422
+ tool_timeout_sec = 30
423
+ enabled_tools = ["search"]
424
+ disabled_tools = []
425
+ ```
426
+
427
+ A streamable HTTP server:
428
+
429
+ ```toml
430
+ [mcp_servers.issues]
431
+ url = "https://example.com/mcp"
432
+ transport = "http"
433
+ http_headers = { "X-Client" = "Happy Agent" }
434
+ bearer_token_env_var = "ISSUES_MCP_TOKEN"
435
+ oauth_client_id_env_var = "MCP_CLIENT_ID"
436
+ oauth_client_secret_env_var = "MCP_CLIENT_SECRET"
437
+ oauth_scopes = ["tools:read"]
438
+ enabled = true
439
+ startup_timeout_sec = 10
440
+ tool_timeout_sec = 30
441
+ enabled_tools = ["search"]
442
+ disabled_tools = []
443
+ ```
444
+
445
+ Exactly one of `command` and `url` must be present. `transport` is only accepted
446
+ as `"http"`; a `command` entry is stdio implicitly. Unknown keys in an
447
+ `[mcp_servers.*]` table are a configuration error, so do not guess names.
448
+
449
+ MCP tools, resources, resource templates, prompts, pagination, form elicitation,
450
+ bearer tokens, and OAuth client credentials are supported, and live tool
451
+ discovery lets a session use tools added after startup.
452
+
453
+ ### Boundary rules
454
+
455
+ These are product rules, enforced on the tool definitions themselves:
456
+
457
+ - Every MCP tool sets `requiresAutoOrFullAccess: true`, because the server can
458
+ act outside Happy Agent's local sandbox. MCP is unavailable in Read only and Workspace
459
+ write.
460
+ - Every direct and dynamic MCP tool invocation is reviewed in Auto
461
+ (`shouldReviewInAutoMode: () => true`), and the approval text discloses the
462
+ external boundary.
463
+ - Happy Agent-owned protocol operations that are intrinsically read-only skip review:
464
+ `list_mcp_tools`, `list_mcp_resources`, `list_mcp_resource_templates`,
465
+ `read_mcp_resource`, and `list_mcp_prompts`. The operations that reach the
466
+ server to do something — `call_mcp_tool` and `get_mcp_prompt` — are reviewed.
467
+ - Server-supplied annotations such as `readOnlyHint` are untrusted metadata. They
468
+ are never authorization evidence and never a reason to skip review.
469
+ - MCP settings coming from a project require a one-time trust decision before the
470
+ server starts. The decision is fingerprinted and stored, and Happy Agent asks again if
471
+ the server configuration changes.
472
+ - Stdio servers run as local processes with the daemon environment and are **not**
473
+ restricted by the session filesystem sandbox. Only configure servers you trust.
474
+
475
+ Plugin-contributed MCP servers travel the same composite provider path as
476
+ configured ones, so tool assembly, `AgentContext`, and `PermissionContext`
477
+ behavior stay shared.
478
+
479
+ ---
480
+
481
+ ## Happy Agent client and integrations
482
+
483
+ External applications drive the daemon through `@slopus/happy-agent-client`.
484
+ The host supplies a Fetch implementation and bearer token; the client exposes
485
+ the typed `/v0` request and SSE contracts without reading credentials or daemon
486
+ state directly. See `packages/happy-agent/API.md` for the complete public
487
+ surface.
488
+
489
+ ### Other integration surfaces
490
+
491
+ - **Project and workspace files** — `GET`/`PUT` `/projects/{id}/file` and
492
+ `/projects/{id}/workspaces/{id}/file`, with SHA-256 optimistic concurrency, a
493
+ 32 MB limit, and Happy Agent's workspace boundary applied.
494
+ - **HTTP proxy** — `CONNECT /projects/{id}/proxy` (and the workspace-scoped form)
495
+ tunnels ordinary HTTP through the authenticated daemon connection.
496
+ - **Happy mobile synchronization** — a first-class daemon feature, gated by both
497
+ the embedder's `happyIntegration` option and the user-wide
498
+ `[settings] happy_integration` config value, both fail-closed.
499
+ - **Remote terminals** — Happy Agent's own libghostty-based terminal protocol. It is
500
+ deliberately unspecified for outside consumers right now: it exists to work
501
+ inside Happy and Happy Agent.
502
+
503
+ ### Planned, not implemented
504
+
505
+ Do not write code against these yet; they are directions rather than features:
506
+
507
+ - **Electron-isolated plugin UI.** Instant mounting under a proper Electron
508
+ isolation mechanism is the goal; the current implementation serves bounded
509
+ static bundles and typed actions and leaves mounting to the host.
510
+ - **A published terminal protocol specification.** The protocol may be improved
511
+ and specified later; today it is proprietary.
512
+ - **A wider plugin API.** The SDK surface grows as plugins ask for it. Extend it
513
+ deliberately rather than reaching around it.
514
+
515
+ Happy Agent deliberately has **no** plugin marketplace, no plugin identifier scheme, no
516
+ plugin permission model, and no separate Happy Agent login flow. These are settled
517
+ non-goals, not gaps to fill.
518
+
519
+ ---
520
+
521
+ ## Subagents and workflows
522
+
523
+ The lightest extension mechanism is runtime, not installed: spawn a subagent with
524
+ its own model and effort, or run a deterministic multi-agent workflow. Nothing is
525
+ compiled and nothing persists — it is how you extend a single task rather than
526
+ the product.
527
+
528
+ Use it when work is bounded and parallelizable (research, review, verification),
529
+ or when a job is genuinely a pipeline over many items. Every subagent needs an
530
+ explicit model and effort; nothing is inherited.
531
+
532
+ Full guidance — when to delegate, choosing models and effort, background agents,
533
+ agent-to-agent messaging, and workflow scripting — is in
534
+ [`agents-and-collaboration.md`](agents-and-collaboration.md).
535
+
536
+ ---
537
+
538
+ ## Rules that apply to every extension
539
+
540
+ - **One permission model.** Codex, Claude, Pi, Grok, MCP, and plugin tools all
541
+ execute through the same `AgentContext`, filesystem boundary, shell sandbox,
542
+ and `PermissionContext`. Provider differences belong in tool names, argument
543
+ schemas, and result formatting — never in a separate security path.
544
+ - **Each tool owns its Auto behavior.** `shouldReviewInAutoMode` is required.
545
+ Define `shouldRunInFullAccessInAutoMode` only when a reviewed action must cross
546
+ the sandbox; review alone must not imply elevation. Never dispatch permission
547
+ behavior from a tool-name list, prefix, or provider key.
548
+ - **Common tools are assembled once.** A capability that belongs to Happy Agent rather
549
+ than a vendor goes through the shared common-tool entry point so any future
550
+ model picks it up without per-provider work.
551
+ - **TypeBox for all runtime validation.** Derive TypeScript types with `Static`;
552
+ do not hand-write parallel interfaces or ad hoc type predicates.
553
+ - **Early-stage compatibility.** Change schemas and behavior directly instead of
554
+ adding aliases or migration branches — but never edit an existing database
555
+ migration.
556
+ - **Use `pnpm`.** Never `npm`, `npx`, or `yarn`.
557
+ - **Test at the boundary.** For anything spanning terminal input or rendering,
558
+ inference, tools, processes, filesystem effects, or permissions, write a gym
559
+ test, and reproduce a bug in the gym before changing production code.
560
+ - **User-facing text is human-readable English.** Convert identifiers, enum
561
+ values, and file names into clear display text before rendering them.