@roackb2/heddle 0.0.13 → 0.0.14

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 (67) hide show
  1. package/README.md +283 -217
  2. package/dist/src/cli/daemon.d.ts +14 -0
  3. package/dist/src/cli/daemon.d.ts.map +1 -0
  4. package/dist/src/cli/daemon.js +61 -0
  5. package/dist/src/cli/daemon.js.map +1 -0
  6. package/dist/src/cli/main.js +6 -0
  7. package/dist/src/cli/main.js.map +1 -1
  8. package/dist/src/server/app.d.ts +6 -0
  9. package/dist/src/server/app.d.ts.map +1 -0
  10. package/dist/src/server/app.js +36 -0
  11. package/dist/src/server/app.js.map +1 -0
  12. package/dist/src/server/dev.d.ts +2 -0
  13. package/dist/src/server/dev.d.ts.map +1 -0
  14. package/dist/src/server/dev.js +39 -0
  15. package/dist/src/server/dev.js.map +1 -0
  16. package/dist/src/server/features/control-plane/router.d.ts +37 -0
  17. package/dist/src/server/features/control-plane/router.d.ts.map +1 -0
  18. package/dist/src/server/features/control-plane/router.js +34 -0
  19. package/dist/src/server/features/control-plane/router.js.map +1 -0
  20. package/dist/src/server/features/control-plane/services/chat-sessions.d.ts +4 -0
  21. package/dist/src/server/features/control-plane/services/chat-sessions.d.ts.map +1 -0
  22. package/dist/src/server/features/control-plane/services/chat-sessions.js +63 -0
  23. package/dist/src/server/features/control-plane/services/chat-sessions.js.map +1 -0
  24. package/dist/src/server/features/control-plane/services/control-plane-state.d.ts +4 -0
  25. package/dist/src/server/features/control-plane/services/control-plane-state.d.ts.map +1 -0
  26. package/dist/src/server/features/control-plane/services/control-plane-state.js +19 -0
  27. package/dist/src/server/features/control-plane/services/control-plane-state.js.map +1 -0
  28. package/dist/src/server/features/control-plane/services/heartbeat.d.ts +7 -0
  29. package/dist/src/server/features/control-plane/services/heartbeat.d.ts.map +1 -0
  30. package/dist/src/server/features/control-plane/services/heartbeat.js +12 -0
  31. package/dist/src/server/features/control-plane/services/heartbeat.js.map +1 -0
  32. package/dist/src/server/features/control-plane/types.d.ts +31 -0
  33. package/dist/src/server/features/control-plane/types.d.ts.map +1 -0
  34. package/dist/src/server/features/control-plane/types.js +2 -0
  35. package/dist/src/server/features/control-plane/types.js.map +1 -0
  36. package/dist/src/server/index.d.ts +8 -0
  37. package/dist/src/server/index.d.ts.map +1 -0
  38. package/dist/src/server/index.js +42 -0
  39. package/dist/src/server/index.js.map +1 -0
  40. package/dist/src/server/logger.d.ts +8 -0
  41. package/dist/src/server/logger.d.ts.map +1 -0
  42. package/dist/src/server/logger.js +11 -0
  43. package/dist/src/server/logger.js.map +1 -0
  44. package/dist/src/server/middleware/request-logging.d.ts +4 -0
  45. package/dist/src/server/middleware/request-logging.d.ts.map +1 -0
  46. package/dist/src/server/middleware/request-logging.js +15 -0
  47. package/dist/src/server/middleware/request-logging.js.map +1 -0
  48. package/dist/src/server/router.d.ts +55 -0
  49. package/dist/src/server/router.d.ts.map +1 -0
  50. package/dist/src/server/router.js +14 -0
  51. package/dist/src/server/router.js.map +1 -0
  52. package/dist/src/server/static.d.ts +4 -0
  53. package/dist/src/server/static.d.ts.map +1 -0
  54. package/dist/src/server/static.js +25 -0
  55. package/dist/src/server/static.js.map +1 -0
  56. package/dist/src/server/trpc.d.ts +9 -0
  57. package/dist/src/server/trpc.d.ts.map +1 -0
  58. package/dist/src/server/trpc.js +5 -0
  59. package/dist/src/server/trpc.js.map +1 -0
  60. package/dist/src/server/types.d.ts +17 -0
  61. package/dist/src/server/types.d.ts.map +1 -0
  62. package/dist/src/server/types.js +2 -0
  63. package/dist/src/server/types.js.map +1 -0
  64. package/dist/src/web/assets/index-DmYQXJQf.css +1 -0
  65. package/dist/src/web/assets/index-xFJTOaTY.js +9 -0
  66. package/dist/src/web/index.html +13 -0
  67. package/package.json +18 -3
package/README.md CHANGED
@@ -10,6 +10,19 @@ Heddle is designed to make live agent runs more observable, not just easier to l
10
10
 
11
11
  If you are interested in the underlying methodology, Heddle's drift telemetry is powered by [CyberLoop on npm](https://www.npmjs.com/package/cyberloop). See the [CyberLoop repository](https://github.com/roackb2/cyberloop) and [paper](https://zenodo.org/records/18138161) for the geometric-control and trajectory-based details.
12
12
 
13
+ ## Agenda
14
+
15
+ - [Chat And CLI Usage](#chat-and-cli-usage)
16
+ - [Control Plane](#control-plane)
17
+ - [Knowledge Persistence](#knowledge-persistence)
18
+ - [Semantic Drift](#semantic-drift)
19
+ - [Heartbeat](#heartbeat)
20
+ - [Programmatic Use](#programmatic-use)
21
+ - [Capability Details](#capability-details)
22
+ - [Supported Providers And Models](#supported-providers-and-models)
23
+ - [Project Config](#project-config)
24
+ - [Design Direction](#design-direction)
25
+
13
26
  ## How Heddle Helps
14
27
 
15
28
  - daily development work in real coding projects
@@ -24,6 +37,7 @@ If you are interested in the underlying methodology, Heddle's drift telemetry is
24
37
  - provider-agnostic model support across OpenAI and Anthropic
25
38
  - embeddable `runAgentLoop` API for building non-CLI agent hosts
26
39
  - `runAgentHeartbeat` for scheduler-driven autonomous wake cycles without chat by default
40
+ - native React/Vite control plane served by `heddle daemon` for local browser-based oversight
27
41
  - serializable checkpoints for resume, background execution, and hosted workers
28
42
  - host-facing heartbeat task/run views plus websocket-friendly status/progress/response adapters
29
43
  - provider-backed hosted web search through `web_search`
@@ -70,7 +84,9 @@ If you are developing inside the Heddle repo itself, `yarn install` also install
70
84
 
71
85
  For local development against the full CLI entrypoint, use `yarn cli:dev`. The `chat:dev` scripts intentionally start chat mode directly and do not route subcommands such as `heartbeat`.
72
86
 
73
- ## Quick Start
87
+ ## Chat And CLI Usage
88
+
89
+ ### Quick Start
74
90
 
75
91
  1. Set an API key for a supported provider.
76
92
 
@@ -96,34 +112,165 @@ Heddle uses the current directory as the workspace root unless you pass `--cwd`.
96
112
 
97
113
  The default workflow is interactive chat, not one-shot prompts. You keep a session open, inspect the repo, switch models, run direct shell commands when needed, and continue earlier sessions later.
98
114
 
99
- ## Core Capabilities
115
+ ### Chat Workflow
100
116
 
101
- Heddle currently supports:
117
+ Start chat in the current repo:
102
118
 
103
- - repository inspection with `list_files`, `read_file`, and `search_files`
104
- - code and doc changes with `edit_file`
105
- - provider-backed hosted web search through `web_search`
106
- - local screenshot and image inspection through `view_image`
107
- - inline `@file` mentions for file-priority context without pasting file contents into the prompt
108
- - shell execution with inspect vs approval-gated mutate behavior
109
- - multi-turn chat sessions with saved history under `.heddle/`
110
- - session management with create, switch, continue, rename, and close flows
111
- - automatic conversation compaction so longer chats preserve context instead of growing unbounded
112
- - manual `/compact` to shrink the current session transcript on demand
113
- - persistent workspace memory notes under `.heddle/memory/`
114
- - serializable run checkpoints for programmatic hosts and later continuation
115
- - short working-plan support through `update_plan` for substantial multi-step tasks
116
- - remembered per-project approvals for repeated commands and edits
117
- - interrupt and resume support for longer-running coding workflows
118
- - request-size aware context tracking in chat so the footer reflects model input usage, not only raw history size
119
+ ```bash
120
+ heddle
121
+ heddle chat
122
+ heddle --cwd /path/to/project
123
+ heddle chat --model gpt-5.4-mini --max-steps 20
124
+ ```
119
125
 
120
- The image workflow is intentionally simple for now: users can reference a local image path in chat, and the agent can decide whether to inspect it with `view_image`. Heddle does not require a full multimodal attachment model for this first version.
126
+ Typical chat use cases:
121
127
 
122
- The file-mention workflow is also intentionally lightweight: `@path/to/file` tells Heddle that the file is important context and should be inspected before answering, but it does not automatically inline the file contents into the prompt.
128
+ - ask Heddle to explain architecture, code paths, tests, or build setup
129
+ - iterate on a fix over multiple prompts instead of fitting everything into one request
130
+ - inspect files, search the repo, and edit code inside one persistent session
131
+ - keep a long coding conversation usable through saved sessions, `/continue`, automatic history compaction, and manual `/compact`
132
+ - let the agent create and update a short working plan for a multi-step implementation
133
+ - search official docs or other current external references with provider-backed `web_search`
134
+ - mention important repo files with `@path/to/file` so the agent treats them as first-pass context
135
+ - reference a local screenshot path and have the agent inspect it with `view_image`
136
+ - run direct shell commands from chat with `!<command>`
137
+ - pause and later resume earlier sessions
123
138
 
124
- The planning workflow is also intentionally lightweight: Heddle does not force a heavyweight planner or a separate "plan mode," but it can automatically record and update a short plan when a task is substantial enough to benefit from visible progress tracking.
139
+ Useful chat commands:
125
140
 
126
- The web-search workflow is provider-backed rather than crawler-backed: OpenAI models use OpenAI-hosted web search, and Anthropic models use Anthropic-hosted web search when available through the selected model/tool path.
141
+ - `/help`: show local chat commands
142
+ - `/continue`: resume the current session from its last interrupted or prior run
143
+ - `/model`: show the active model
144
+ - `/model list`: show the built-in shortlist
145
+ - `/model set <query>`: open the interactive model picker
146
+ - `/model <name>`: switch models directly
147
+ - `/session list`: list recent saved sessions
148
+ - `/session choose <query>`: choose a recent session interactively
149
+ - `/session new [name]`: create a new session
150
+ - `/session switch <id>`: switch to another session
151
+ - `/session continue <id>`: switch and immediately continue that session
152
+ - `/session rename <name>`: rename the current session
153
+ - `/session close <id>`: remove a saved session
154
+ - `/clear`: clear the current transcript
155
+ - `/compact`: compact older session history immediately
156
+ - `/drift`: show CyberLoop semantic drift detection status
157
+ - `/drift on`: re-enable observe-only CyberLoop kinematics telemetry for chat runs
158
+ - `/drift off`: disable CyberLoop semantic drift detection
159
+ - `!<command>`: run a shell command directly in chat
160
+
161
+ Direct shell in chat:
162
+
163
+ ```bash
164
+ !pwd
165
+ !git status
166
+ !yarn test
167
+ ```
168
+
169
+ Read-oriented commands stay in inspect mode when possible. Workspace-changing or unclassified commands fall back to approval-gated execution.
170
+
171
+ Chat state is stored under `.heddle/`, including saved sessions, traces, approvals, and memory notes. The footer context indicator is an estimate of total request input against the active model's context window, not only the raw chat history length.
172
+
173
+ For local development against the sibling CyberLoop repo, run chat with the middleware module path:
174
+
175
+ ```bash
176
+ HEDDLE_CYBERLOOP_ADVANCED_MODULE=/Users/roackb2/Studio/projects/CyberLoop/src/advanced/kinematics-middleware.ts yarn chat:dev:openai
177
+ ```
178
+
179
+ Drift telemetry is enabled by default for new sessions. For installed usage, install the optional `cyberloop` peer dependency in the same environment as Heddle so it can dynamically import `cyberloop/advanced`.
180
+
181
+ ### CLI Commands
182
+
183
+ Supported commands:
184
+
185
+ - `heddle` or `heddle chat`: start interactive chat mode
186
+ - `heddle ask "<goal>"`: run a single prompt and exit
187
+ - `heddle heartbeat start [--every 30m] [--task "<durable task>"]`: create or enable the default heartbeat task and run the foreground scheduler
188
+ - `heddle heartbeat task add --id <id> --task "<durable task>" [--every 15m]`: create or update a scheduled heartbeat task
189
+ - `heddle heartbeat task list`: list local heartbeat tasks
190
+ - `heddle heartbeat task show <id>`: show a task's schedule, last decision, and last run summary
191
+ - `heddle heartbeat task enable <id>` / `heddle heartbeat task disable <id>`: toggle a heartbeat task
192
+ - `heddle heartbeat run --once`: run due heartbeat tasks once
193
+ - `heddle heartbeat run [--poll 60s]`: run the foreground heartbeat scheduler until interrupted; heartbeat runs print scheduler, agent, tool, decision, and checkpoint progress events
194
+ - `heddle heartbeat runs list [--task <id>] [--limit 10]`: list saved heartbeat run records
195
+ - `heddle heartbeat runs show <run-id|latest> [--task <id>]`: show the final agent output for a saved heartbeat run
196
+ - `heddle init`: create a `heddle.config.json` template in the current project
197
+
198
+ Common flags:
199
+
200
+ - `--cwd <path>`: run against another workspace root
201
+ - `--model <name>`: choose the active model
202
+ - `--max-steps <n>`: limit the agent loop length
203
+
204
+ ## Control Plane
205
+
206
+ Heddle includes an early local browser control plane for users who want a native UI instead of only terminal chat or third-party messaging apps.
207
+
208
+ This is still WIP. The current version is useful for read-only oversight, but it is not yet a full replacement for the TUI.
209
+
210
+ Current stack:
211
+
212
+ - `src/server`: Express-hosted tRPC server
213
+ - `src/web`: React/Vite web client
214
+ - `src/server/features/control-plane`: control-plane-specific server feature logic
215
+ - pino logs written locally for debugging
216
+
217
+ Start the daemon from a workspace:
218
+
219
+ ```bash
220
+ heddle daemon
221
+ ```
222
+
223
+ By default, the daemon binds to `127.0.0.1:8765` and serves the built web app plus the tRPC API. The first implementation surfaces:
224
+
225
+ - workspace and `.heddle/` state location
226
+ - saved chat session inventory
227
+ - heartbeat task status
228
+ - recent heartbeat run summaries and usage
229
+
230
+ You can override host and port:
231
+
232
+ ```bash
233
+ heddle daemon --host 127.0.0.1 --port 8765
234
+ ```
235
+
236
+ For local development, run the server and client separately:
237
+
238
+ ```bash
239
+ yarn server:dev
240
+ yarn client:dev
241
+ ```
242
+
243
+ `yarn server:dev` starts the tRPC server at `127.0.0.1:8765`. `yarn client:dev` starts the Vite client and proxies `/trpc` to the server.
244
+
245
+ The server writes pino logs to `.heddle/logs/server.log` by default. Override the path with:
246
+
247
+ ```bash
248
+ HEDDLE_SERVER_LOG_FILE=/path/to/server.log yarn server:dev
249
+ ```
250
+
251
+ This control plane is intentionally read-only at first. The next milestones are session detail views, chat continuation from the browser, heartbeat task actions, and live run updates.
252
+
253
+ ## Knowledge Persistence
254
+
255
+ Heddle can maintain durable workspace knowledge under `.heddle/memory/`.
256
+
257
+ The goal is to help Heddle learn from real project work over time instead of rediscovering the same stable facts every session.
258
+
259
+ Typical examples:
260
+
261
+ - architecture notes that future sessions should reuse
262
+ - recurring build, test, or environment quirks
263
+ - important repo conventions and command patterns
264
+ - durable findings from completed implementation work
265
+
266
+ The memory model is intentionally simple:
267
+
268
+ - memory is stored as readable markdown files in the project state directory
269
+ - Heddle can list, read, search, and edit those notes
270
+ - shell tools are still available when flexible retrieval or editing is needed
271
+ - memory is meant for stable, reusable knowledge, not scratch notes or speculative plans
272
+
273
+ This is one of Heddle's more distinctive host-side capabilities: the aim is not just to answer the current prompt, but to let the runtime accumulate project understanding from your operations and become more useful across sessions.
127
274
 
128
275
  ## Semantic Drift
129
276
 
@@ -257,200 +404,6 @@ const runs = await listHeartbeatRunViews(store, { taskId: 'repo-gardener', limit
257
404
 
258
405
  Those views are intentionally smaller than full checkpoints or traces. They expose stable operator-facing fields such as task ID, status, progress, decision, outcome, resumability, usage, and latest summary.
259
406
 
260
- ## Knowledge Persistence
261
-
262
- Heddle can maintain durable workspace knowledge under `.heddle/memory/`.
263
-
264
- The goal is to help Heddle learn from real project work over time instead of rediscovering the same stable facts every session.
265
-
266
- Typical examples:
267
-
268
- - architecture notes that future sessions should reuse
269
- - recurring build, test, or environment quirks
270
- - important repo conventions and command patterns
271
- - durable findings from completed implementation work
272
-
273
- The memory model is intentionally simple:
274
-
275
- - memory is stored as readable markdown files in the project state directory
276
- - Heddle can list, read, search, and edit those notes
277
- - shell tools are still available when flexible retrieval or editing is needed
278
- - memory is meant for stable, reusable knowledge, not scratch notes or speculative plans
279
-
280
- This is one of Heddle's more distinctive host-side capabilities: the aim is not just to answer the current prompt, but to let the runtime accumulate project understanding from your operations and become more useful across sessions.
281
-
282
- ## What Heddle Does
283
-
284
- Heddle runs an agent loop against your workspace:
285
-
286
- ```text
287
- goal
288
- -> send transcript + tool definitions to the model
289
- -> model answers or requests tool calls
290
- -> execute tools in the workspace
291
- -> append results to the transcript
292
- -> continue until done / max steps / error
293
- ```
294
-
295
- Current focus:
296
-
297
- - chat-first coding and repository workflows from the terminal
298
- - minimal runtime behavior instead of a large framework surface
299
- - traceability and operator control over hidden orchestration
300
-
301
- ## Chat Workflow
302
-
303
- Start chat in the current repo:
304
-
305
- ```bash
306
- heddle
307
- heddle chat
308
- heddle --cwd /path/to/project
309
- heddle chat --model gpt-5.4-mini --max-steps 20
310
- ```
311
-
312
- Typical chat use cases:
313
-
314
- - ask Heddle to explain architecture, code paths, tests, or build setup
315
- - iterate on a fix over multiple prompts instead of fitting everything into one request
316
- - inspect files, search the repo, and edit code inside one persistent session
317
- - keep a long coding conversation usable through saved sessions, `/continue`, automatic history compaction, and manual `/compact`
318
- - let the agent create and update a short working plan for a multi-step implementation
319
- - search official docs or other current external references with provider-backed `web_search`
320
- - mention important repo files with `@path/to/file` so the agent treats them as first-pass context
321
- - reference a local screenshot path and have the agent inspect it with `view_image`
322
- - run direct shell commands from chat with `!<command>`
323
- - pause and later resume earlier sessions
324
-
325
- Useful chat commands:
326
-
327
- - `/help`: show local chat commands
328
- - `/continue`: resume the current session from its last interrupted or prior run
329
- - `/model`: show the active model
330
- - `/model list`: show the built-in shortlist
331
- - `/model set <query>`: open the interactive model picker
332
- - `/model <name>`: switch models directly
333
- - `/session list`: list recent saved sessions
334
- - `/session choose <query>`: choose a recent session interactively
335
- - `/session new [name]`: create a new session
336
- - `/session switch <id>`: switch to another session
337
- - `/session continue <id>`: switch and immediately continue that session
338
- - `/session rename <name>`: rename the current session
339
- - `/session close <id>`: remove a saved session
340
- - `/clear`: clear the current transcript
341
- - `/compact`: compact older session history immediately
342
- - `/drift`: show CyberLoop semantic drift detection status
343
- - `/drift on`: re-enable observe-only CyberLoop kinematics telemetry for chat runs
344
- - `/drift off`: disable CyberLoop semantic drift detection
345
- - `!<command>`: run a shell command directly in chat
346
-
347
- Direct shell in chat:
348
-
349
- ```bash
350
- !pwd
351
- !git status
352
- !yarn test
353
- ```
354
-
355
- Read-oriented commands stay in inspect mode when possible. Workspace-changing or unclassified commands fall back to approval-gated execution.
356
-
357
- Chat state is stored under `.heddle/`, including saved sessions, traces, approvals, and memory notes. The footer context indicator is an estimate of total request input against the active model's context window, not only the raw chat history length.
358
-
359
- For local development against the sibling CyberLoop repo, run chat with the middleware module path:
360
-
361
- ```bash
362
- HEDDLE_CYBERLOOP_ADVANCED_MODULE=/Users/roackb2/Studio/projects/CyberLoop/src/advanced/kinematics-middleware.ts yarn chat:dev:openai
363
- ```
364
-
365
- Drift telemetry is enabled by default for new sessions. For installed usage, install the optional `cyberloop` peer dependency in the same environment as Heddle so it can dynamically import `cyberloop/advanced`.
366
-
367
- ## CLI Usage
368
-
369
- Supported commands:
370
-
371
- - `heddle` or `heddle chat`: start interactive chat mode
372
- - `heddle ask "<goal>"`: run a single prompt and exit
373
- - `heddle heartbeat start [--every 30m] [--task "<durable task>"]`: create or enable the default heartbeat task and run the foreground scheduler
374
- - `heddle heartbeat task add --id <id> --task "<durable task>" [--every 15m]`: create or update a scheduled heartbeat task
375
- - `heddle heartbeat task list`: list local heartbeat tasks
376
- - `heddle heartbeat task show <id>`: show a task's schedule, last decision, and last run summary
377
- - `heddle heartbeat task enable <id>` / `heddle heartbeat task disable <id>`: toggle a heartbeat task
378
- - `heddle heartbeat run --once`: run due heartbeat tasks once
379
- - `heddle heartbeat run [--poll 60s]`: run the foreground heartbeat scheduler until interrupted; heartbeat runs print scheduler, agent, tool, decision, and checkpoint progress events
380
- - `heddle heartbeat runs list [--task <id>] [--limit 10]`: list saved heartbeat run records
381
- - `heddle heartbeat runs show <run-id|latest> [--task <id>]`: show the final agent output for a saved heartbeat run
382
- - `heddle init`: create a `heddle.config.json` template in the current project
383
-
384
- Common flags:
385
-
386
- - `--cwd <path>`: run against another workspace root
387
- - `--model <name>`: choose the active model
388
- - `--max-steps <n>`: limit the agent loop length
389
-
390
- ## Supported Providers And Models
391
-
392
- Heddle currently has working adapters for:
393
-
394
- - OpenAI
395
- - Anthropic
396
-
397
- Environment variables:
398
-
399
- - `OPENAI_API_KEY` for OpenAI models
400
- - `ANTHROPIC_API_KEY` for Anthropic models
401
- - dev fallback env vars are also accepted: `PERSONAL_OPENAI_API_KEY` and `PERSONAL_ANTHROPIC_API_KEY`
402
-
403
- Default models:
404
-
405
- - OpenAI: `gpt-5.1-codex`
406
- - Anthropic: `claude-sonnet-4-6`
407
-
408
- Built-in model shortlist exposed by the CLI UI:
409
-
410
- - OpenAI: `gpt-5.4`, `gpt-5.4-pro`, `gpt-5.4-mini`, `gpt-5.4-nano`
411
- - OpenAI: `gpt-5`, `gpt-5-pro`, `gpt-5-mini`, `gpt-5-nano`
412
- - OpenAI: `gpt-5.2`, `gpt-5.2-pro`, `gpt-5.1`
413
- - OpenAI: `gpt-4.1`, `gpt-4.1-mini`, `gpt-4.1-nano`
414
- - OpenAI: `o3-pro`, `o3`, `o3-mini`, `o4-mini`
415
- - OpenAI coding models: `gpt-5.1-codex`, `gpt-5.1-codex-max`, `gpt-5.1-codex-mini`
416
- - Anthropic: `claude-opus-4-6`, `claude-sonnet-4-6`, `claude-haiku-4-5`
417
- - Anthropic: `claude-opus-4-1`, `claude-opus-4-0`, `claude-sonnet-4-0`
418
- - Anthropic: `claude-3-7-sonnet-latest`
419
- - Anthropic: `claude-3-5-sonnet-latest`, `claude-3-5-haiku-latest`
420
-
421
- Notes:
422
-
423
- - model selection is inferred from the model name prefix
424
- - Gemini model names are recognized by provider inference, but a Google adapter is not wired yet
425
- - you can pass another model name with `--model`, but it only works if the corresponding provider adapter supports it
426
-
427
- ## Project Config
428
-
429
- You can store project defaults in `heddle.config.json`:
430
-
431
- ```json
432
- {
433
- "model": "gpt-5.1-codex",
434
- "maxSteps": 40,
435
- "stateDir": ".heddle",
436
- "directShellApproval": "never",
437
- "searchIgnoreDirs": [".git", "dist", "node_modules", ".heddle"],
438
- "agentContextPaths": ["AGENTS.md"]
439
- }
440
- ```
441
-
442
- Precedence order:
443
-
444
- - CLI flags override `heddle.config.json`
445
- - `heddle.config.json` overrides environment-driven defaults
446
-
447
- Field notes:
448
-
449
- - `stateDir`: where traces, logs, approvals, and chat state are stored
450
- - `directShellApproval`: whether explicit `!command` input in chat still asks for approval
451
- - `searchIgnoreDirs`: directories excluded from `search_files`
452
- - `agentContextPaths`: project instruction files injected into the system prompt
453
-
454
407
  ## Programmatic Use
455
408
 
456
409
  The npm package exports a programmatic execution loop for building other agent hosts on top of Heddle.
@@ -623,6 +576,119 @@ yarn example:cyberloop-observer
623
576
 
624
577
  The public API lives in [src/index.ts](/Users/roackb2/Studio/projects/ProjectHeddle/heddle/src/index.ts).
625
578
 
579
+ ## Capability Details
580
+
581
+ Heddle currently supports:
582
+
583
+ - repository inspection with `list_files`, `read_file`, and `search_files`
584
+ - code and doc changes with `edit_file`
585
+ - provider-backed hosted web search through `web_search`
586
+ - local screenshot and image inspection through `view_image`
587
+ - native browser control plane through `heddle daemon`
588
+ - inline `@file` mentions for file-priority context without pasting file contents into the prompt
589
+ - shell execution with inspect vs approval-gated mutate behavior
590
+ - multi-turn chat sessions with saved history under `.heddle/`
591
+ - session management with create, switch, continue, rename, and close flows
592
+ - automatic conversation compaction so longer chats preserve context instead of growing unbounded
593
+ - manual `/compact` to shrink the current session transcript on demand
594
+ - persistent workspace memory notes under `.heddle/memory/`
595
+ - serializable run checkpoints for programmatic hosts and later continuation
596
+ - short working-plan support through `update_plan` for substantial multi-step tasks
597
+ - remembered per-project approvals for repeated commands and edits
598
+ - interrupt and resume support for longer-running coding workflows
599
+ - request-size aware context tracking in chat so the footer reflects model input usage, not only raw history size
600
+
601
+ The image workflow is intentionally simple for now: users can reference a local image path in chat, and the agent can decide whether to inspect it with `view_image`. Heddle does not require a full multimodal attachment model for this first version.
602
+
603
+ The file-mention workflow is also intentionally lightweight: `@path/to/file` tells Heddle that the file is important context and should be inspected before answering, but it does not automatically inline the file contents into the prompt.
604
+
605
+ The planning workflow is also intentionally lightweight: Heddle does not force a heavyweight planner or a separate "plan mode," but it can automatically record and update a short plan when a task is substantial enough to benefit from visible progress tracking.
606
+
607
+ The web-search workflow is provider-backed rather than crawler-backed: OpenAI models use OpenAI-hosted web search, and Anthropic models use Anthropic-hosted web search when available through the selected model/tool path.
608
+
609
+ ## What Heddle Does
610
+
611
+ Heddle runs an agent loop against your workspace:
612
+
613
+ ```text
614
+ goal
615
+ -> send transcript + tool definitions to the model
616
+ -> model answers or requests tool calls
617
+ -> execute tools in the workspace
618
+ -> append results to the transcript
619
+ -> continue until done / max steps / error
620
+ ```
621
+
622
+ Current focus:
623
+
624
+ - chat-first coding and repository workflows from the terminal
625
+ - minimal runtime behavior instead of a large framework surface
626
+ - traceability and operator control over hidden orchestration
627
+
628
+ ## Supported Providers And Models
629
+
630
+ Heddle currently has working adapters for:
631
+
632
+ - OpenAI
633
+ - Anthropic
634
+
635
+ Environment variables:
636
+
637
+ - `OPENAI_API_KEY` for OpenAI models
638
+ - `ANTHROPIC_API_KEY` for Anthropic models
639
+ - dev fallback env vars are also accepted: `PERSONAL_OPENAI_API_KEY` and `PERSONAL_ANTHROPIC_API_KEY`
640
+
641
+ Default models:
642
+
643
+ - OpenAI: `gpt-5.1-codex`
644
+ - Anthropic: `claude-sonnet-4-6`
645
+
646
+ Built-in model shortlist exposed by the CLI UI:
647
+
648
+ - OpenAI: `gpt-5.4`, `gpt-5.4-pro`, `gpt-5.4-mini`, `gpt-5.4-nano`
649
+ - OpenAI: `gpt-5`, `gpt-5-pro`, `gpt-5-mini`, `gpt-5-nano`
650
+ - OpenAI: `gpt-5.2`, `gpt-5.2-pro`, `gpt-5.1`
651
+ - OpenAI: `gpt-4.1`, `gpt-4.1-mini`, `gpt-4.1-nano`
652
+ - OpenAI: `o3-pro`, `o3`, `o3-mini`, `o4-mini`
653
+ - OpenAI coding models: `gpt-5.1-codex`, `gpt-5.1-codex-max`, `gpt-5.1-codex-mini`
654
+ - Anthropic: `claude-opus-4-6`, `claude-sonnet-4-6`, `claude-haiku-4-5`
655
+ - Anthropic: `claude-opus-4-1`, `claude-opus-4-0`, `claude-sonnet-4-0`
656
+ - Anthropic: `claude-3-7-sonnet-latest`
657
+ - Anthropic: `claude-3-5-sonnet-latest`, `claude-3-5-haiku-latest`
658
+
659
+ Notes:
660
+
661
+ - model selection is inferred from the model name prefix
662
+ - Gemini model names are recognized by provider inference, but a Google adapter is not wired yet
663
+ - you can pass another model name with `--model`, but it only works if the corresponding provider adapter supports it
664
+
665
+ ## Project Config
666
+
667
+ You can store project defaults in `heddle.config.json`:
668
+
669
+ ```json
670
+ {
671
+ "model": "gpt-5.1-codex",
672
+ "maxSteps": 40,
673
+ "stateDir": ".heddle",
674
+ "directShellApproval": "never",
675
+ "searchIgnoreDirs": [".git", "dist", "node_modules", ".heddle"],
676
+ "agentContextPaths": ["AGENTS.md"]
677
+ }
678
+ ```
679
+
680
+ Precedence order:
681
+
682
+ - CLI flags override `heddle.config.json`
683
+ - `heddle.config.json` overrides environment-driven defaults
684
+
685
+ Field notes:
686
+
687
+ - `stateDir`: where traces, logs, approvals, and chat state are stored
688
+ - `directShellApproval`: whether explicit `!command` input in chat still asks for approval
689
+ - `searchIgnoreDirs`: directories excluded from `search_files`
690
+ - `agentContextPaths`: project instruction files injected into the system prompt
691
+
626
692
  ## Design Direction
627
693
 
628
694
  Heddle is currently optimized for coding and terminal workflows, but the long-term goal is broader: an open, provider-agnostic runtime for tool-using agents in real working environments.
@@ -0,0 +1,14 @@
1
+ import { projectChatSessionView } from '../server/index.js';
2
+ export type DaemonCliOptions = {
3
+ workspaceRoot?: string;
4
+ stateDir?: string;
5
+ };
6
+ export type DaemonArgs = {
7
+ host: string;
8
+ port: number;
9
+ assetsDir?: string;
10
+ };
11
+ export { projectChatSessionView };
12
+ export declare function runDaemonCli(args: string[], options?: DaemonCliOptions): Promise<void>;
13
+ export declare function parseDaemonArgs(args: string[]): DaemonArgs;
14
+ //# sourceMappingURL=daemon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../../../src/cli/daemon.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,sBAAsB,EACvB,MAAM,oBAAoB,CAAC;AAG5B,MAAM,MAAM,gBAAgB,GAAG;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAKF,OAAO,EAAE,sBAAsB,EAAE,CAAC;AAElC,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,gBAAqB,iBAahF;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CAO1D"}
@@ -0,0 +1,61 @@
1
+ import { resolve } from 'node:path';
2
+ import { listenHeddleServer, projectChatSessionView, } from '../server/index.js';
3
+ const DEFAULT_HOST = '127.0.0.1';
4
+ const DEFAULT_PORT = 8765;
5
+ export { projectChatSessionView };
6
+ export async function runDaemonCli(args, options = {}) {
7
+ const parsed = parseDaemonArgs(args);
8
+ const workspaceRoot = options.workspaceRoot ?? process.cwd();
9
+ const stateDir = options.stateDir ?? '.heddle';
10
+ const listenOptions = {
11
+ workspaceRoot,
12
+ stateRoot: resolve(workspaceRoot, stateDir),
13
+ host: parsed.host,
14
+ port: parsed.port,
15
+ assetsDir: parsed.assetsDir,
16
+ };
17
+ await listenHeddleServer(listenOptions);
18
+ }
19
+ export function parseDaemonArgs(args) {
20
+ const flags = parseFlags(args);
21
+ return {
22
+ host: stringFlag(flags, 'host') ?? DEFAULT_HOST,
23
+ port: parsePort(stringFlag(flags, 'port')) ?? DEFAULT_PORT,
24
+ assetsDir: stringFlag(flags, 'assets-dir'),
25
+ };
26
+ }
27
+ function parseFlags(args) {
28
+ const flags = {};
29
+ for (let index = 0; index < args.length; index++) {
30
+ const arg = args[index] ?? '';
31
+ if (!arg.startsWith('--')) {
32
+ continue;
33
+ }
34
+ const eqIndex = arg.indexOf('=');
35
+ if (eqIndex > 0) {
36
+ flags[arg.slice(2, eqIndex)] = arg.slice(eqIndex + 1);
37
+ continue;
38
+ }
39
+ const name = arg.slice(2);
40
+ const next = args[index + 1];
41
+ if (!next || next.startsWith('--')) {
42
+ flags[name] = true;
43
+ continue;
44
+ }
45
+ flags[name] = next;
46
+ index++;
47
+ }
48
+ return flags;
49
+ }
50
+ function stringFlag(flags, name) {
51
+ const value = flags[name];
52
+ return typeof value === 'string' ? value : undefined;
53
+ }
54
+ function parsePort(raw) {
55
+ if (!raw) {
56
+ return undefined;
57
+ }
58
+ const value = Number.parseInt(raw, 10);
59
+ return Number.isFinite(value) && value > 0 && value <= 65_535 ? value : undefined;
60
+ }
61
+ //# sourceMappingURL=daemon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../../../src/cli/daemon.ts"],"names":[],"mappings":"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"}
@@ -5,6 +5,7 @@ import { existsSync, readFileSync, writeFileSync } from 'node:fs';
5
5
  import { startChatCli } from './chat/index.js';
6
6
  import { runAskCli } from './ask.js';
7
7
  import { runHeartbeatCli } from './heartbeat.js';
8
+ import { runDaemonCli } from './daemon.js';
8
9
  async function main() {
9
10
  const parsed = parseCli(process.argv.slice(2));
10
11
  const workspaceRoot = resolve(parsed.flags.cwd ?? process.cwd());
@@ -35,6 +36,10 @@ async function main() {
35
36
  await runHeartbeatCli(parsed.rest, resolved);
36
37
  return;
37
38
  }
39
+ if (parsed.command === 'daemon') {
40
+ await runDaemonCli(parsed.rest, resolved);
41
+ return;
42
+ }
38
43
  if (parsed.command === '--help' || parsed.command === '-h' || parsed.command === 'help') {
39
44
  printHelp();
40
45
  return;
@@ -132,6 +137,7 @@ function printHelp() {
132
137
  ' heddle heartbeat run [--poll 60s]',
133
138
  ' heddle heartbeat runs list [--task <id>] [--limit 10]',
134
139
  ' heddle heartbeat runs show <run-id|latest> [--task <id>]',
140
+ ' heddle daemon [--host 127.0.0.1] [--port 8765]',
135
141
  ' heddle init [--cwd <path>]',
136
142
  '',
137
143
  'Project config:',