@draht/coding-agent 2026.3.6 → 2026.3.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.
- package/CHANGELOG.md +88 -0
- package/README.md +6 -2
- package/bin/draht-tools.cjs +187 -32
- package/dist/cli/args.d.ts +6 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +24 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/attach-mode.d.ts +13 -0
- package/dist/cli/attach-mode.d.ts.map +1 -0
- package/dist/cli/attach-mode.js +97 -0
- package/dist/cli/attach-mode.js.map +1 -0
- package/dist/cli/list-sessions.d.ts +8 -0
- package/dist/cli/list-sessions.d.ts.map +1 -0
- package/dist/cli/list-sessions.js +52 -0
- package/dist/cli/list-sessions.js.map +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +2 -2
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts +1 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +50 -17
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts +2 -1
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +25 -1
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/compaction/utils.d.ts +3 -0
- package/dist/core/compaction/utils.d.ts.map +1 -1
- package/dist/core/compaction/utils.js +16 -1
- package/dist/core/compaction/utils.js.map +1 -1
- package/dist/core/export-html/index.d.ts +5 -2
- package/dist/core/export-html/index.d.ts.map +1 -1
- package/dist/core/export-html/index.js +4 -3
- package/dist/core/export-html/index.js.map +1 -1
- package/dist/core/export-html/template.js +11 -14
- package/dist/core/export-html/tool-renderer.d.ts +5 -2
- package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
- package/dist/core/export-html/tool-renderer.js +12 -5
- package/dist/core/export-html/tool-renderer.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +6 -6
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +3 -2
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +32 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +21 -2
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +2 -2
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +2 -2
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +1 -1
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +7 -0
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/settings-manager.d.ts +4 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +36 -2
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/socket-server/discovery.d.ts +19 -0
- package/dist/core/socket-server/discovery.d.ts.map +1 -0
- package/dist/core/socket-server/discovery.js +91 -0
- package/dist/core/socket-server/discovery.js.map +1 -0
- package/dist/core/socket-server/index.d.ts +13 -0
- package/dist/core/socket-server/index.d.ts.map +1 -0
- package/dist/core/socket-server/index.js +11 -0
- package/dist/core/socket-server/index.js.map +1 -0
- package/dist/core/socket-server/session-integration.d.ts +17 -0
- package/dist/core/socket-server/session-integration.d.ts.map +1 -0
- package/dist/core/socket-server/session-integration.js +77 -0
- package/dist/core/socket-server/session-integration.js.map +1 -0
- package/dist/core/socket-server/socket-client.d.ts +65 -0
- package/dist/core/socket-server/socket-client.d.ts.map +1 -0
- package/dist/core/socket-server/socket-client.js +197 -0
- package/dist/core/socket-server/socket-client.js.map +1 -0
- package/dist/core/socket-server/socket-server.d.ts +60 -0
- package/dist/core/socket-server/socket-server.d.ts.map +1 -0
- package/dist/core/socket-server/socket-server.js +273 -0
- package/dist/core/socket-server/socket-server.js.map +1 -0
- package/dist/core/socket-server/types.d.ts +81 -0
- package/dist/core/socket-server/types.d.ts.map +1 -0
- package/dist/core/socket-server/types.js +8 -0
- package/dist/core/socket-server/types.js.map +1 -0
- package/dist/gsd/domain.d.ts +5 -1
- package/dist/gsd/domain.d.ts.map +1 -1
- package/dist/gsd/domain.js +71 -1
- package/dist/gsd/domain.js.map +1 -1
- package/dist/gsd/git.d.ts.map +1 -1
- package/dist/gsd/git.js +18 -0
- package/dist/gsd/git.js.map +1 -1
- package/dist/gsd/index.d.ts +1 -0
- package/dist/gsd/index.d.ts.map +1 -1
- package/dist/gsd/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +76 -11
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-editor.js +1 -0
- package/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +8 -23
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +2 -0
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +10 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +14 -4
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts +21 -2
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +115 -9
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +66 -5
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/rpc/jsonl.d.ts +17 -0
- package/dist/modes/rpc/jsonl.d.ts.map +1 -0
- package/dist/modes/rpc/jsonl.js +49 -0
- package/dist/modes/rpc/jsonl.js.map +1 -0
- package/dist/modes/rpc/rpc-client.d.ts +1 -1
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +7 -11
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +9 -11
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/prompts/commands/execute-phase.md +2 -2
- package/dist/prompts/commands/fix.md +2 -2
- package/dist/prompts/commands/plan-phase.md +5 -1
- package/dist/prompts/commands/quick.md +5 -1
- package/dist/utils/changelog.d.ts +12 -0
- package/dist/utils/changelog.d.ts.map +1 -1
- package/dist/utils/changelog.js +25 -14
- package/dist/utils/changelog.js.map +1 -1
- package/dist/utils/notify.d.ts +12 -0
- package/dist/utils/notify.d.ts.map +1 -0
- package/dist/utils/notify.js +41 -0
- package/dist/utils/notify.js.map +1 -0
- package/docs/compaction.md +2 -0
- package/docs/custom-provider.md +11 -7
- package/docs/extensions.md +55 -3
- package/docs/keybindings.md +9 -1
- package/docs/models.md +5 -1
- package/docs/rpc.md +40 -3
- package/docs/session.md +2 -2
- package/docs/settings.md +1 -0
- package/docs/terminal-setup.md +28 -3
- package/docs/tmux.md +61 -0
- package/docs/tree.md +9 -0
- package/examples/extensions/antigravity-image-gen.ts +5 -4
- package/examples/extensions/custom-provider-gitlab-duo/test.ts +2 -2
- package/examples/extensions/notify.ts +9 -2
- package/examples/extensions/overlay-qa-tests.ts +468 -1
- package/examples/extensions/preset.ts +2 -3
- package/examples/extensions/provider-payload.ts +14 -0
- package/examples/extensions/sandbox/index.ts +2 -3
- package/examples/extensions/tool-override.ts +2 -3
- package/examples/extensions/with-deps/index.ts +1 -5
- package/package.json +7 -5
- package/prompts/commands/execute-phase.md +2 -2
- package/prompts/commands/fix.md +2 -2
- package/prompts/commands/plan-phase.md +5 -1
- package/prompts/commands/quick.md +5 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,93 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2026.3.14] - 2026-03-14
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- built-in terminal notification on agent turn end
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- fix(coding-agent): use getAgentDir() in example extensions (#2009)
|
|
12
|
+
- Export the structured mapping contract through the public GSD entrypoint
|
|
13
|
+
- Add typed extraction results to GSD domain mapping
|
|
14
|
+
- consolidate quality gate fixture helpers
|
|
15
|
+
- Cover strict-mode TypeScript error detection
|
|
16
|
+
- add TypeScript-error quality gate scenario
|
|
17
|
+
- Cover passing and failing test-suite outcomes
|
|
18
|
+
- add failing test-suite quality gate scenario
|
|
19
|
+
- Create a real-hook quality gate test harness
|
|
20
|
+
- add real quality gate hook harness test
|
|
21
|
+
- verify phase 21 lifecycle execution logs
|
|
22
|
+
- add failing phase 21 execution log verification test
|
|
23
|
+
- exercise phase 21 lifecycle task commit flow
|
|
24
|
+
- add failing phase 21 lifecycle commit flow test
|
|
25
|
+
- define mapCodebase structured extraction contract
|
|
26
|
+
- build phase 21 lifecycle workspace fixture
|
|
27
|
+
- add failing phase 21 lifecycle fixture test
|
|
28
|
+
- reduce duplicated domain fixture assertions
|
|
29
|
+
- Create a stable domain fixture codebase
|
|
30
|
+
- replace gsd structure checks with runtime loading coverage
|
|
31
|
+
- specify stable GSD domain fixture exports
|
|
32
|
+
- add gsd extension runtime loading spec
|
|
33
|
+
- extract reusable temp git repo setup steps
|
|
34
|
+
- Implement the shared git repo helper
|
|
35
|
+
- specify isolated temp git repo helper behavior
|
|
36
|
+
|
|
37
|
+
### Fixed
|
|
38
|
+
|
|
39
|
+
- add stdin support to all draht-tools write commands
|
|
40
|
+
- add cmux support to notify example extension
|
|
41
|
+
- add stdin support to create-quick-plan and fix plan prompts to pipe actual content
|
|
42
|
+
- use conventional commit prefixes instead of TDD annotations in prompt templates
|
|
43
|
+
- restore phase 21 verification baseline
|
|
44
|
+
- The draht-tools create-plan command now reads stdin content when piped
|
|
45
|
+
- handle date-based version suffixes in changelog parsing
|
|
46
|
+
- change default update instruction to bun add -g
|
|
47
|
+
|
|
48
|
+
## [2026.3.11] - 2026-03-11
|
|
49
|
+
|
|
50
|
+
### Added
|
|
51
|
+
|
|
52
|
+
- add fold/unfold to tree branch navigation
|
|
53
|
+
- refine session_directory hook closes #1729
|
|
54
|
+
- add session_directory extension event
|
|
55
|
+
- add provider payload hook
|
|
56
|
+
- preserve custom editor onEscape/onCtrlD handlers
|
|
57
|
+
- add treeFilterMode setting for /tree default filter (#1852)
|
|
58
|
+
- add experimental attachable sessions
|
|
59
|
+
|
|
60
|
+
### Changed
|
|
61
|
+
|
|
62
|
+
- fix upstream branding in cherry-picked files
|
|
63
|
+
- explain Windows Terminal Alt+Enter remap (#1967)
|
|
64
|
+
- add codex tool-loop cache probe
|
|
65
|
+
- document tool result truncation in compaction serialization
|
|
66
|
+
- clarify that tool errors must be thrown, not returned
|
|
67
|
+
- clarify models.json name behavior (fixes #1840)
|
|
68
|
+
- update session path from ~/.pi/ to ~/.draht/
|
|
69
|
+
|
|
70
|
+
### Fixed
|
|
71
|
+
|
|
72
|
+
- add missing @sinclair/typebox and ajv dependencies
|
|
73
|
+
- update Anthropic compaction model and HTTPS package test (#1960)
|
|
74
|
+
- use shell for external editor on windows closes #1925
|
|
75
|
+
- prefer explicit -e extensions closes #1896
|
|
76
|
+
- handle tmux xterm extended keys and warn on tmux setup fixes #1872
|
|
77
|
+
- custom tool collapsed/expanded rendering in HTML export (#1934)
|
|
78
|
+
- use strict JSONL framing fixes #1911
|
|
79
|
+
- keep ~/.agents skills user-scoped\n\ncloses #1915
|
|
80
|
+
- guard against stale kept pre-compaction usage in error-path threshold check
|
|
81
|
+
- truncate tool results in compaction summarization to prevent overflow, fixes #1796
|
|
82
|
+
- allow threshold compaction for error messages using last successful usage, fixes #1834
|
|
83
|
+
- retry sync lockfile acquisition to prevent false auth errors during parallel startup
|
|
84
|
+
- preserve thinking defaults across model switches closes #1864
|
|
85
|
+
- clear header on /new closes #1880
|
|
86
|
+
- prefer workspace dist files for extension aliases
|
|
87
|
+
- normalize CRLF in write preview rendering (fixes #1854)
|
|
88
|
+
- make footer truncation width-aware
|
|
89
|
+
- use ESM resolution for extension alias fallback (#1821)
|
|
90
|
+
|
|
3
91
|
## [2026.3.6] - 2026-03-06
|
|
4
92
|
|
|
5
93
|
### Added
|
package/README.md
CHANGED
|
@@ -59,7 +59,7 @@ draht
|
|
|
59
59
|
|
|
60
60
|
Then just talk to draht. By default, draht gives the model four tools: `read`, `write`, `edit`, and `bash`. The model uses these to fulfill your requests. Add capabilities via [skills](#skills), [prompt templates](#prompt-templates), [extensions](#extensions), or [draht packages](#draht-packages).
|
|
61
61
|
|
|
62
|
-
**Platform notes:** [Windows](docs/windows.md) | [Termux (Android)](docs/termux.md) | [Terminal setup](docs/terminal-setup.md) | [Shell aliases](docs/shell-aliases.md)
|
|
62
|
+
**Platform notes:** [Windows](docs/windows.md) | [Termux (Android)](docs/termux.md) | [tmux](docs/tmux.md) | [Terminal setup](docs/terminal-setup.md) | [Shell aliases](docs/shell-aliases.md)
|
|
63
63
|
|
|
64
64
|
---
|
|
65
65
|
|
|
@@ -177,6 +177,8 @@ Submit messages while the agent is working:
|
|
|
177
177
|
- **Escape** aborts and restores queued messages to editor
|
|
178
178
|
- **Alt+Up** retrieves queued messages back to editor
|
|
179
179
|
|
|
180
|
+
On Windows Terminal, `Alt+Enter` is fullscreen by default. Remap it in [docs/terminal-setup.md](docs/terminal-setup.md) so pi can receive the follow-up shortcut.
|
|
181
|
+
|
|
180
182
|
Configure delivery in [settings](docs/settings.md): `steeringMode` and `followUpMode` can be `"one-at-a-time"` (default, waits for response) or `"all"` (delivers all queued at once). `transport` selects provider transport preference (`"sse"`, `"websocket"`, or `"auto"`) for providers that support multiple transports.
|
|
181
183
|
|
|
182
184
|
---
|
|
@@ -202,7 +204,7 @@ draht --session <path> # Use specific session file or ID
|
|
|
202
204
|
|
|
203
205
|
<p align="center"><img src="docs/images/tree-view.png" alt="Tree View" width="600"></p>
|
|
204
206
|
|
|
205
|
-
- Search by typing, page with ←/→
|
|
207
|
+
- Search by typing, fold/unfold and jump between branches with Ctrl+←/Ctrl+→ or Alt+←/Alt+→, page with ←/→
|
|
206
208
|
- Filter modes (Ctrl+O): default → no-tools → user-only → labeled-only → all
|
|
207
209
|
- Press `l` to label entries as bookmarks
|
|
208
210
|
|
|
@@ -386,6 +388,8 @@ For non-Node.js integrations, use RPC mode over stdin/stdout:
|
|
|
386
388
|
draht --mode rpc
|
|
387
389
|
```
|
|
388
390
|
|
|
391
|
+
RPC mode uses strict LF-delimited JSONL framing. Clients must split records on `\n` only. Do not use generic line readers like Node `readline`, which also split on Unicode separators inside JSON payloads.
|
|
392
|
+
|
|
389
393
|
See [docs/rpc.md](docs/rpc.md) for the protocol.
|
|
390
394
|
|
|
391
395
|
---
|
package/bin/draht-tools.cjs
CHANGED
|
@@ -305,7 +305,8 @@ commands["phase-info"] = function (n) {
|
|
|
305
305
|
};
|
|
306
306
|
|
|
307
307
|
// --- save-context ---
|
|
308
|
-
|
|
308
|
+
// Supports stdin: echo "content" | draht-tools save-context N
|
|
309
|
+
commands["save-context"] = async function (n, ...rest) {
|
|
309
310
|
const num = parseInt(n, 10);
|
|
310
311
|
if (!num) { console.error("Usage: draht-tools save-context N"); process.exit(1); }
|
|
311
312
|
|
|
@@ -314,7 +315,22 @@ commands["save-context"] = function (n, ...rest) {
|
|
|
314
315
|
ensureDir(dir);
|
|
315
316
|
|
|
316
317
|
const contextPath = path.join(dir, `${padNum(num)}-CONTEXT.md`);
|
|
317
|
-
|
|
318
|
+
|
|
319
|
+
// Check for stdin content (piped input)
|
|
320
|
+
let stdinContent = "";
|
|
321
|
+
if (!process.stdin.isTTY) {
|
|
322
|
+
stdinContent = await new Promise((resolve) => {
|
|
323
|
+
let data = "";
|
|
324
|
+
process.stdin.setEncoding("utf-8");
|
|
325
|
+
process.stdin.on("data", (chunk) => { data += chunk; });
|
|
326
|
+
process.stdin.on("end", () => { resolve(data.trim()); });
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if (stdinContent) {
|
|
331
|
+
writeMd(contextPath, stdinContent);
|
|
332
|
+
console.log(`Created: ${contextPath}`);
|
|
333
|
+
} else if (fs.existsSync(contextPath)) {
|
|
318
334
|
console.log(`Context already exists at ${contextPath}`);
|
|
319
335
|
console.log("Edit it directly or pass content via stdin.");
|
|
320
336
|
} else {
|
|
@@ -372,7 +388,8 @@ commands["load-phase-context"] = function (n) {
|
|
|
372
388
|
};
|
|
373
389
|
|
|
374
390
|
// --- create-plan ---
|
|
375
|
-
|
|
391
|
+
// Supports stdin: echo "content" | draht-tools create-plan N P [title]
|
|
392
|
+
commands["create-plan"] = async function (n, p, ...titleWords) {
|
|
376
393
|
const phaseNum = parseInt(n, 10);
|
|
377
394
|
const planNum = parseInt(p, 10);
|
|
378
395
|
if (!phaseNum || !planNum) { console.error("Usage: draht-tools create-plan N P [title]"); process.exit(1); }
|
|
@@ -384,7 +401,24 @@ commands["create-plan"] = function (n, p, ...titleWords) {
|
|
|
384
401
|
const title = titleWords.join(" ") || `Plan ${planNum}`;
|
|
385
402
|
const planPath = path.join(dir, `${padNum(phaseNum)}-${padNum(planNum)}-PLAN.md`);
|
|
386
403
|
|
|
387
|
-
|
|
404
|
+
// Check for stdin content (piped input)
|
|
405
|
+
let stdinContent = "";
|
|
406
|
+
if (!process.stdin.isTTY) {
|
|
407
|
+
stdinContent = await new Promise((resolve) => {
|
|
408
|
+
let data = "";
|
|
409
|
+
process.stdin.setEncoding("utf-8");
|
|
410
|
+
process.stdin.on("data", (chunk) => { data += chunk; });
|
|
411
|
+
process.stdin.on("end", () => { resolve(data.trim()); });
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
let content;
|
|
416
|
+
if (stdinContent) {
|
|
417
|
+
// Use stdin content directly
|
|
418
|
+
content = stdinContent;
|
|
419
|
+
} else {
|
|
420
|
+
// Generate template
|
|
421
|
+
content = `---
|
|
388
422
|
phase: ${phaseNum}
|
|
389
423
|
plan: ${planNum}
|
|
390
424
|
depends_on: []
|
|
@@ -417,7 +451,9 @@ must_haves:
|
|
|
417
451
|
---
|
|
418
452
|
Created: ${timestamp()}
|
|
419
453
|
`;
|
|
420
|
-
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
writeMd(planPath, content);
|
|
421
457
|
console.log(`Created: ${planPath}`);
|
|
422
458
|
};
|
|
423
459
|
|
|
@@ -547,7 +583,8 @@ commands["commit-task"] = function (n, p, t, ...desc) {
|
|
|
547
583
|
};
|
|
548
584
|
|
|
549
585
|
// --- write-summary ---
|
|
550
|
-
|
|
586
|
+
// Supports stdin: echo "content" | draht-tools write-summary N P
|
|
587
|
+
commands["write-summary"] = async function (n, p) {
|
|
551
588
|
const phaseNum = parseInt(n, 10);
|
|
552
589
|
const planNum = parseInt(p, 10);
|
|
553
590
|
if (!phaseNum || !planNum) { console.error("Usage: draht-tools write-summary N P"); process.exit(1); }
|
|
@@ -556,8 +593,26 @@ commands["write-summary"] = function (n, p) {
|
|
|
556
593
|
if (!phaseDir) { console.error(`Phase ${phaseNum} not found`); process.exit(1); }
|
|
557
594
|
|
|
558
595
|
const summaryPath = path.join(phaseDir, `${padNum(phaseNum)}-${padNum(planNum)}-SUMMARY.md`);
|
|
559
|
-
|
|
560
|
-
|
|
596
|
+
|
|
597
|
+
// Check for stdin content (piped input)
|
|
598
|
+
let stdinContent = "";
|
|
599
|
+
if (!process.stdin.isTTY) {
|
|
600
|
+
stdinContent = await new Promise((resolve) => {
|
|
601
|
+
let data = "";
|
|
602
|
+
process.stdin.setEncoding("utf-8");
|
|
603
|
+
process.stdin.on("data", (chunk) => { data += chunk; });
|
|
604
|
+
process.stdin.on("end", () => { resolve(data.trim()); });
|
|
605
|
+
});
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
let content;
|
|
609
|
+
if (stdinContent) {
|
|
610
|
+
content = stdinContent;
|
|
611
|
+
} else {
|
|
612
|
+
content = `# Phase ${phaseNum}, Plan ${planNum} Summary\n\n## Completed Tasks\n| # | Task | Status | Commit |\n|---|------|--------|--------|\n| 1 | [task] | ✅ Done | [hash] |\n\n## Files Changed\n- [files]\n\n## Verification Results\n- [results]\n\n## Notes\n[deviations, decisions]\n\n---\nCompleted: ${timestamp()}\n`;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
writeMd(summaryPath, content);
|
|
561
616
|
console.log(`Created: ${summaryPath}`);
|
|
562
617
|
};
|
|
563
618
|
|
|
@@ -628,17 +683,35 @@ commands["extract-deliverables"] = function (n) {
|
|
|
628
683
|
};
|
|
629
684
|
|
|
630
685
|
// --- create-fix-plan ---
|
|
631
|
-
|
|
686
|
+
// Supports stdin: echo "content" | draht-tools create-fix-plan N P [issue]
|
|
687
|
+
commands["create-fix-plan"] = async function (n, p, ...issueWords) {
|
|
632
688
|
const phaseNum = parseInt(n, 10);
|
|
633
689
|
const planNum = parseInt(p, 10);
|
|
634
690
|
if (!phaseNum || !planNum) { console.error("Usage: draht-tools create-fix-plan N P [issue]"); process.exit(1); }
|
|
635
691
|
|
|
636
692
|
const slug = getPhaseSlug(phaseNum) || `phase-${phaseNum}`;
|
|
637
693
|
const dir = planningPath("phases", `${padNum(phaseNum)}-${slug}`);
|
|
694
|
+
ensureDir(dir);
|
|
638
695
|
const issue = issueWords.join(" ") || "Fix identified issues";
|
|
639
696
|
|
|
640
697
|
const fixPath = path.join(dir, `${padNum(phaseNum)}-${padNum(planNum)}-FIX-PLAN.md`);
|
|
641
|
-
|
|
698
|
+
|
|
699
|
+
// Check for stdin content (piped input)
|
|
700
|
+
let stdinContent = "";
|
|
701
|
+
if (!process.stdin.isTTY) {
|
|
702
|
+
stdinContent = await new Promise((resolve) => {
|
|
703
|
+
let data = "";
|
|
704
|
+
process.stdin.setEncoding("utf-8");
|
|
705
|
+
process.stdin.on("data", (chunk) => { data += chunk; });
|
|
706
|
+
process.stdin.on("end", () => { resolve(data.trim()); });
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
let content;
|
|
711
|
+
if (stdinContent) {
|
|
712
|
+
content = stdinContent;
|
|
713
|
+
} else {
|
|
714
|
+
content = `---
|
|
642
715
|
gap_closure: true
|
|
643
716
|
fixes_plan: ${planNum}
|
|
644
717
|
issue: "${issue}"
|
|
@@ -662,12 +735,15 @@ ${issue}
|
|
|
662
735
|
---
|
|
663
736
|
Created: ${timestamp()}
|
|
664
737
|
`;
|
|
665
|
-
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
writeMd(fixPath, content);
|
|
666
741
|
console.log(`Created: ${fixPath}`);
|
|
667
742
|
};
|
|
668
743
|
|
|
669
744
|
// --- write-uat ---
|
|
670
|
-
|
|
745
|
+
// Supports stdin: echo "content" | draht-tools write-uat N
|
|
746
|
+
commands["write-uat"] = async function (n) {
|
|
671
747
|
const num = parseInt(n, 10);
|
|
672
748
|
if (!num) { console.error("Usage: draht-tools write-uat N"); process.exit(1); }
|
|
673
749
|
|
|
@@ -675,8 +751,26 @@ commands["write-uat"] = function (n) {
|
|
|
675
751
|
if (!phaseDir) { console.error(`Phase ${num} not found`); process.exit(1); }
|
|
676
752
|
|
|
677
753
|
const uatPath = path.join(phaseDir, `${padNum(num)}-UAT.md`);
|
|
678
|
-
|
|
679
|
-
|
|
754
|
+
|
|
755
|
+
// Check for stdin content (piped input)
|
|
756
|
+
let stdinContent = "";
|
|
757
|
+
if (!process.stdin.isTTY) {
|
|
758
|
+
stdinContent = await new Promise((resolve) => {
|
|
759
|
+
let data = "";
|
|
760
|
+
process.stdin.setEncoding("utf-8");
|
|
761
|
+
process.stdin.on("data", (chunk) => { data += chunk; });
|
|
762
|
+
process.stdin.on("end", () => { resolve(data.trim()); });
|
|
763
|
+
});
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
let content;
|
|
767
|
+
if (stdinContent) {
|
|
768
|
+
content = stdinContent;
|
|
769
|
+
} else {
|
|
770
|
+
content = `# Phase ${num} User Acceptance Testing\n\n## Test Date: ${dateStamp()}\n\n## Results\n| # | Deliverable | Status | Notes |\n|---|-------------|--------|-------|\n| 1 | [description] | ✅ Pass | |\n\n## Summary\n- Passed: X/Y\n- Failed: 0/Y\n- Skipped: 0/Y\n\n## Fix Plans Created\n(none)\n`;
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
writeMd(uatPath, content);
|
|
680
774
|
console.log(`Created: ${uatPath}`);
|
|
681
775
|
};
|
|
682
776
|
|
|
@@ -691,7 +785,8 @@ commands["next-quick-number"] = function () {
|
|
|
691
785
|
};
|
|
692
786
|
|
|
693
787
|
// --- create-quick-plan ---
|
|
694
|
-
|
|
788
|
+
// Supports stdin: echo "content" | draht-tools create-quick-plan NNN [desc]
|
|
789
|
+
commands["create-quick-plan"] = async function (n, ...descWords) {
|
|
695
790
|
const num = padNum(parseInt(n, 10), 3);
|
|
696
791
|
const desc = descWords.join(" ") || "Quick task";
|
|
697
792
|
const slug = slugify(desc);
|
|
@@ -699,13 +794,34 @@ commands["create-quick-plan"] = function (n, ...descWords) {
|
|
|
699
794
|
ensureDir(dir);
|
|
700
795
|
|
|
701
796
|
const planPath = path.join(dir, `${num}-PLAN.md`);
|
|
702
|
-
|
|
703
|
-
|
|
797
|
+
|
|
798
|
+
// Check for stdin content (piped input)
|
|
799
|
+
let stdinContent = "";
|
|
800
|
+
if (!process.stdin.isTTY) {
|
|
801
|
+
stdinContent = await new Promise((resolve) => {
|
|
802
|
+
let data = "";
|
|
803
|
+
process.stdin.setEncoding("utf-8");
|
|
804
|
+
process.stdin.on("data", (chunk) => { data += chunk; });
|
|
805
|
+
process.stdin.on("end", () => { resolve(data.trim()); });
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
let content;
|
|
810
|
+
if (stdinContent) {
|
|
811
|
+
// Use stdin content directly
|
|
812
|
+
content = stdinContent;
|
|
813
|
+
} else {
|
|
814
|
+
// Generate template
|
|
815
|
+
content = `# Quick Task ${num}: ${desc}\n\n## Tasks\n\n<task type="auto">\n <n>[Task]</n>\n <files>[files]</files>\n <action>[instructions]</action>\n <verify>[verify]</verify>\n <done>[done]</done>\n</task>\n\n---\nCreated: ${timestamp()}\n`;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
writeMd(planPath, content);
|
|
704
819
|
console.log(`Created: ${planPath}`);
|
|
705
820
|
};
|
|
706
821
|
|
|
707
822
|
// --- write-quick-summary ---
|
|
708
|
-
|
|
823
|
+
// Supports stdin: echo "content" | draht-tools write-quick-summary NNN
|
|
824
|
+
commands["write-quick-summary"] = async function (n) {
|
|
709
825
|
const num = padNum(parseInt(n, 10), 3);
|
|
710
826
|
const dir = planningPath("quick");
|
|
711
827
|
if (!fs.existsSync(dir)) { console.error("No quick tasks directory"); process.exit(1); }
|
|
@@ -713,8 +829,26 @@ commands["write-quick-summary"] = function (n) {
|
|
|
713
829
|
if (!match) { console.error(`Quick task ${num} not found`); process.exit(1); }
|
|
714
830
|
|
|
715
831
|
const summaryPath = path.join(dir, match, `${num}-SUMMARY.md`);
|
|
716
|
-
|
|
717
|
-
|
|
832
|
+
|
|
833
|
+
// Check for stdin content (piped input)
|
|
834
|
+
let stdinContent = "";
|
|
835
|
+
if (!process.stdin.isTTY) {
|
|
836
|
+
stdinContent = await new Promise((resolve) => {
|
|
837
|
+
let data = "";
|
|
838
|
+
process.stdin.setEncoding("utf-8");
|
|
839
|
+
process.stdin.on("data", (chunk) => { data += chunk; });
|
|
840
|
+
process.stdin.on("end", () => { resolve(data.trim()); });
|
|
841
|
+
});
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
let content;
|
|
845
|
+
if (stdinContent) {
|
|
846
|
+
content = stdinContent;
|
|
847
|
+
} else {
|
|
848
|
+
content = `# Quick Task ${num} Summary\n\n## Tasks Completed\n| # | Task | Status | Commit |\n|---|------|--------|--------|\n| 1 | [task] | ✅ Done | [hash] |\n\n## Files Changed\n- [files]\n\n---\nCompleted: ${timestamp()}\n`;
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
writeMd(summaryPath, content);
|
|
718
852
|
console.log(`Created: ${summaryPath}`);
|
|
719
853
|
};
|
|
720
854
|
|
|
@@ -826,7 +960,8 @@ commands["commit-docs"] = function (...msg) {
|
|
|
826
960
|
};
|
|
827
961
|
|
|
828
962
|
// --- research-phase ---
|
|
829
|
-
|
|
963
|
+
// Supports stdin: echo "content" | draht-tools research-phase N
|
|
964
|
+
commands["research-phase"] = async function (n) {
|
|
830
965
|
const num = parseInt(n, 10);
|
|
831
966
|
if (!num) { console.error("Usage: draht-tools research-phase N"); process.exit(1); }
|
|
832
967
|
|
|
@@ -835,10 +970,28 @@ commands["research-phase"] = function (n) {
|
|
|
835
970
|
ensureDir(dir);
|
|
836
971
|
|
|
837
972
|
const resPath = path.join(dir, `${padNum(num)}-RESEARCH.md`);
|
|
838
|
-
|
|
839
|
-
|
|
973
|
+
|
|
974
|
+
// Check for stdin content (piped input)
|
|
975
|
+
let stdinContent = "";
|
|
976
|
+
if (!process.stdin.isTTY) {
|
|
977
|
+
stdinContent = await new Promise((resolve) => {
|
|
978
|
+
let data = "";
|
|
979
|
+
process.stdin.setEncoding("utf-8");
|
|
980
|
+
process.stdin.on("data", (chunk) => { data += chunk; });
|
|
981
|
+
process.stdin.on("end", () => { resolve(data.trim()); });
|
|
982
|
+
});
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
let content;
|
|
986
|
+
if (stdinContent) {
|
|
987
|
+
content = stdinContent;
|
|
988
|
+
} else {
|
|
989
|
+
content = `# Phase ${num} Research\n\nGenerated: ${timestamp()}\n\n## Best Practices\n[Fill in]\n\n## Patterns & Anti-Patterns\n[Fill in]\n\n## Library Recommendations\n[Fill in]\n\n## Edge Cases & Gotchas\n[Fill in]\n`;
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
writeMd(resPath, content);
|
|
840
993
|
console.log(`Created: ${resPath}`);
|
|
841
|
-
console.log("→ Fill in research findings, then plan the phase.");
|
|
994
|
+
if (!stdinContent) console.log("→ Fill in research findings, then plan the phase.");
|
|
842
995
|
};
|
|
843
996
|
|
|
844
997
|
// ============================================================================
|
|
@@ -902,11 +1055,13 @@ Version: 1.0.0
|
|
|
902
1055
|
// Dispatch
|
|
903
1056
|
const [cmd, ...args] = process.argv.slice(2);
|
|
904
1057
|
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
commands[cmd]
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
1058
|
+
(async () => {
|
|
1059
|
+
if (!cmd || cmd === "help" || cmd === "--help" || cmd === "-h") {
|
|
1060
|
+
commands.help();
|
|
1061
|
+
} else if (commands[cmd]) {
|
|
1062
|
+
await commands[cmd](...args);
|
|
1063
|
+
} else {
|
|
1064
|
+
console.error(`Unknown command: ${cmd}\nRun: draht-tools help`);
|
|
1065
|
+
process.exit(1);
|
|
1066
|
+
}
|
|
1067
|
+
})();
|
package/dist/cli/args.d.ts
CHANGED
|
@@ -35,6 +35,12 @@ export interface Args {
|
|
|
35
35
|
listModels?: string | true;
|
|
36
36
|
offline?: boolean;
|
|
37
37
|
verbose?: boolean;
|
|
38
|
+
/** Experimental: Start session with socket server for multi-attach */
|
|
39
|
+
attachable?: boolean;
|
|
40
|
+
/** Experimental: Attach to an existing socket session */
|
|
41
|
+
attach?: string;
|
|
42
|
+
/** Experimental: List all attachable socket sessions */
|
|
43
|
+
listSessions?: boolean;
|
|
38
44
|
messages: string[];
|
|
39
45
|
fileArgs: string[];
|
|
40
46
|
/** Unknown flags (potentially extension flags) - map of flag name to value */
|
package/dist/cli/args.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGvD,OAAO,EAAY,KAAK,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAEjE,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;AAE3C,MAAM,WAAW,IAAI;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,8EAA8E;IAC9E,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC,CAAC;CAC5C;AAID,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,aAAa,CAE1E;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,cAAc,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,SAAS,GAAG,QAAQ,CAAA;CAAE,CAAC,GAAG,IAAI,CA0H5G;AAED,wBAAgB,SAAS,IAAI,IAAI,CAyIhC","sourcesContent":["/**\n * CLI argument parsing and help display\n */\n\nimport type { ThinkingLevel } from \"@draht/agent-core\";\nimport chalk from \"chalk\";\nimport { APP_NAME, CONFIG_DIR_NAME, ENV_AGENT_DIR } from \"../config.js\";\nimport { allTools, type ToolName } from \"../core/tools/index.js\";\n\nexport type Mode = \"text\" | \"json\" | \"rpc\";\n\nexport interface Args {\n\tprovider?: string;\n\tmodel?: string;\n\tapiKey?: string;\n\tsystemPrompt?: string;\n\tappendSystemPrompt?: string;\n\tthinking?: ThinkingLevel;\n\tcontinue?: boolean;\n\tresume?: boolean;\n\thelp?: boolean;\n\tversion?: boolean;\n\tmode?: Mode;\n\tnoSession?: boolean;\n\tsession?: string;\n\tsessionDir?: string;\n\tmodels?: string[];\n\ttools?: ToolName[];\n\tnoTools?: boolean;\n\textensions?: string[];\n\tnoExtensions?: boolean;\n\tprint?: boolean;\n\texport?: string;\n\tnoSkills?: boolean;\n\tskills?: string[];\n\tpromptTemplates?: string[];\n\tnoPromptTemplates?: boolean;\n\tthemes?: string[];\n\tnoThemes?: boolean;\n\tlistModels?: string | true;\n\toffline?: boolean;\n\tverbose?: boolean;\n\tmessages: string[];\n\tfileArgs: string[];\n\t/** Unknown flags (potentially extension flags) - map of flag name to value */\n\tunknownFlags: Map<string, boolean | string>;\n}\n\nconst VALID_THINKING_LEVELS = [\"off\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\"] as const;\n\nexport function isValidThinkingLevel(level: string): level is ThinkingLevel {\n\treturn VALID_THINKING_LEVELS.includes(level as ThinkingLevel);\n}\n\nexport function parseArgs(args: string[], extensionFlags?: Map<string, { type: \"boolean\" | \"string\" }>): Args {\n\tconst result: Args = {\n\t\tmessages: [],\n\t\tfileArgs: [],\n\t\tunknownFlags: new Map(),\n\t};\n\n\tfor (let i = 0; i < args.length; i++) {\n\t\tconst arg = args[i];\n\n\t\tif (arg === \"--help\" || arg === \"-h\") {\n\t\t\tresult.help = true;\n\t\t} else if (arg === \"--version\" || arg === \"-v\") {\n\t\t\tresult.version = true;\n\t\t} else if (arg === \"--mode\" && i + 1 < args.length) {\n\t\t\tconst mode = args[++i];\n\t\t\tif (mode === \"text\" || mode === \"json\" || mode === \"rpc\") {\n\t\t\t\tresult.mode = mode;\n\t\t\t}\n\t\t} else if (arg === \"--continue\" || arg === \"-c\") {\n\t\t\tresult.continue = true;\n\t\t} else if (arg === \"--resume\" || arg === \"-r\") {\n\t\t\tresult.resume = true;\n\t\t} else if (arg === \"--provider\" && i + 1 < args.length) {\n\t\t\tresult.provider = args[++i];\n\t\t} else if (arg === \"--model\" && i + 1 < args.length) {\n\t\t\tresult.model = args[++i];\n\t\t} else if (arg === \"--api-key\" && i + 1 < args.length) {\n\t\t\tresult.apiKey = args[++i];\n\t\t} else if (arg === \"--system-prompt\" && i + 1 < args.length) {\n\t\t\tresult.systemPrompt = args[++i];\n\t\t} else if (arg === \"--append-system-prompt\" && i + 1 < args.length) {\n\t\t\tresult.appendSystemPrompt = args[++i];\n\t\t} else if (arg === \"--no-session\") {\n\t\t\tresult.noSession = true;\n\t\t} else if (arg === \"--session\" && i + 1 < args.length) {\n\t\t\tresult.session = args[++i];\n\t\t} else if (arg === \"--session-dir\" && i + 1 < args.length) {\n\t\t\tresult.sessionDir = args[++i];\n\t\t} else if (arg === \"--models\" && i + 1 < args.length) {\n\t\t\tresult.models = args[++i].split(\",\").map((s) => s.trim());\n\t\t} else if (arg === \"--no-tools\") {\n\t\t\tresult.noTools = true;\n\t\t} else if (arg === \"--tools\" && i + 1 < args.length) {\n\t\t\tconst toolNames = args[++i].split(\",\").map((s) => s.trim());\n\t\t\tconst validTools: ToolName[] = [];\n\t\t\tfor (const name of toolNames) {\n\t\t\t\tif (name in allTools) {\n\t\t\t\t\tvalidTools.push(name as ToolName);\n\t\t\t\t} else {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\tchalk.yellow(`Warning: Unknown tool \"${name}\". Valid tools: ${Object.keys(allTools).join(\", \")}`),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tresult.tools = validTools;\n\t\t} else if (arg === \"--thinking\" && i + 1 < args.length) {\n\t\t\tconst level = args[++i];\n\t\t\tif (isValidThinkingLevel(level)) {\n\t\t\t\tresult.thinking = level;\n\t\t\t} else {\n\t\t\t\tconsole.error(\n\t\t\t\t\tchalk.yellow(\n\t\t\t\t\t\t`Warning: Invalid thinking level \"${level}\". Valid values: ${VALID_THINKING_LEVELS.join(\", \")}`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t} else if (arg === \"--print\" || arg === \"-p\") {\n\t\t\tresult.print = true;\n\t\t} else if (arg === \"--export\" && i + 1 < args.length) {\n\t\t\tresult.export = args[++i];\n\t\t} else if ((arg === \"--extension\" || arg === \"-e\") && i + 1 < args.length) {\n\t\t\tresult.extensions = result.extensions ?? [];\n\t\t\tresult.extensions.push(args[++i]);\n\t\t} else if (arg === \"--no-extensions\" || arg === \"-ne\") {\n\t\t\tresult.noExtensions = true;\n\t\t} else if (arg === \"--skill\" && i + 1 < args.length) {\n\t\t\tresult.skills = result.skills ?? [];\n\t\t\tresult.skills.push(args[++i]);\n\t\t} else if (arg === \"--prompt-template\" && i + 1 < args.length) {\n\t\t\tresult.promptTemplates = result.promptTemplates ?? [];\n\t\t\tresult.promptTemplates.push(args[++i]);\n\t\t} else if (arg === \"--theme\" && i + 1 < args.length) {\n\t\t\tresult.themes = result.themes ?? [];\n\t\t\tresult.themes.push(args[++i]);\n\t\t} else if (arg === \"--no-skills\" || arg === \"-ns\") {\n\t\t\tresult.noSkills = true;\n\t\t} else if (arg === \"--no-prompt-templates\" || arg === \"-np\") {\n\t\t\tresult.noPromptTemplates = true;\n\t\t} else if (arg === \"--no-themes\") {\n\t\t\tresult.noThemes = true;\n\t\t} else if (arg === \"--list-models\") {\n\t\t\t// Check if next arg is a search pattern (not a flag or file arg)\n\t\t\tif (i + 1 < args.length && !args[i + 1].startsWith(\"-\") && !args[i + 1].startsWith(\"@\")) {\n\t\t\t\tresult.listModels = args[++i];\n\t\t\t} else {\n\t\t\t\tresult.listModels = true;\n\t\t\t}\n\t\t} else if (arg === \"--verbose\") {\n\t\t\tresult.verbose = true;\n\t\t} else if (arg === \"--offline\") {\n\t\t\tresult.offline = true;\n\t\t} else if (arg.startsWith(\"@\")) {\n\t\t\tresult.fileArgs.push(arg.slice(1)); // Remove @ prefix\n\t\t} else if (arg.startsWith(\"--\") && extensionFlags) {\n\t\t\t// Check if it's an extension-registered flag\n\t\t\tconst flagName = arg.slice(2);\n\t\t\tconst extFlag = extensionFlags.get(flagName);\n\t\t\tif (extFlag) {\n\t\t\t\tif (extFlag.type === \"boolean\") {\n\t\t\t\t\tresult.unknownFlags.set(flagName, true);\n\t\t\t\t} else if (extFlag.type === \"string\" && i + 1 < args.length) {\n\t\t\t\t\tresult.unknownFlags.set(flagName, args[++i]);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Unknown flags without extensionFlags are silently ignored (first pass)\n\t\t} else if (!arg.startsWith(\"-\")) {\n\t\t\tresult.messages.push(arg);\n\t\t}\n\t}\n\n\treturn result;\n}\n\nexport function printHelp(): void {\n\tconsole.log(`${chalk.bold(APP_NAME)} - AI coding assistant with read, bash, edit, write tools\n\n${chalk.bold(\"Usage:\")}\n ${APP_NAME} [options] [@files...] [messages...]\n\n${chalk.bold(\"Commands:\")}\n ${APP_NAME} install <source> [-l] Install extension source and add to settings\n ${APP_NAME} remove <source> [-l] Remove extension source from settings\n ${APP_NAME} update [source] Update installed extensions (skips pinned sources)\n ${APP_NAME} list List installed extensions from settings\n ${APP_NAME} config Open TUI to enable/disable package resources\n ${APP_NAME} <command> --help Show help for install/remove/update/list\n\n${chalk.bold(\"Options:\")}\n --provider <name> Provider name (default: google)\n --model <pattern> Model pattern or ID (supports \"provider/id\" and optional \":<thinking>\")\n --api-key <key> API key (defaults to env vars)\n --system-prompt <text> System prompt (default: coding assistant prompt)\n --append-system-prompt <text> Append text or file contents to the system prompt\n --mode <mode> Output mode: text (default), json, or rpc\n --print, -p Non-interactive mode: process prompt and exit\n --continue, -c Continue previous session\n --resume, -r Select a session to resume\n --session <path> Use specific session file\n --session-dir <dir> Directory for session storage and lookup\n --no-session Don't save session (ephemeral)\n --models <patterns> Comma-separated model patterns for Ctrl+P cycling\n Supports globs (anthropic/*, *sonnet*) and fuzzy matching\n --no-tools Disable all built-in tools\n --tools <tools> Comma-separated list of tools to enable (default: read,bash,edit,write)\n Available: read, bash, edit, write, grep, find, ls\n --thinking <level> Set thinking level: off, minimal, low, medium, high, xhigh\n --extension, -e <path> Load an extension file (can be used multiple times)\n --no-extensions, -ne Disable extension discovery (explicit -e paths still work)\n --skill <path> Load a skill file or directory (can be used multiple times)\n --no-skills, -ns Disable skills discovery and loading\n --prompt-template <path> Load a prompt template file or directory (can be used multiple times)\n --no-prompt-templates, -np Disable prompt template discovery and loading\n --theme <path> Load a theme file or directory (can be used multiple times)\n --no-themes Disable theme discovery and loading\n --export <file> Export session file to HTML and exit\n --list-models [search] List available models (with optional fuzzy search)\n --verbose Force verbose startup (overrides quietStartup setting)\n --offline Disable startup network operations (same as DRAHT_OFFLINE=1)\n --help, -h Show this help\n --version, -v Show version number\n\nExtensions can register additional flags (e.g., --plan from plan-mode extension).\n\n${chalk.bold(\"Examples:\")}\n # Interactive mode\n ${APP_NAME}\n\n # Interactive mode with initial prompt\n ${APP_NAME} \"List all .ts files in src/\"\n\n # Include files in initial message\n ${APP_NAME} @prompt.md @image.png \"What color is the sky?\"\n\n # Non-interactive mode (process and exit)\n ${APP_NAME} -p \"List all .ts files in src/\"\n\n # Multiple messages (interactive)\n ${APP_NAME} \"Read package.json\" \"What dependencies do we have?\"\n\n # Continue previous session\n ${APP_NAME} --continue \"What did we discuss?\"\n\n # Use different model\n ${APP_NAME} --provider openai --model gpt-4o-mini \"Help me refactor this code\"\n\n # Use model with provider prefix (no --provider needed)\n ${APP_NAME} --model openai/gpt-4o \"Help me refactor this code\"\n\n # Use model with thinking level shorthand\n ${APP_NAME} --model sonnet:high \"Solve this complex problem\"\n\n # Limit model cycling to specific models\n ${APP_NAME} --models claude-sonnet,claude-haiku,gpt-4o\n\n # Limit to a specific provider with glob pattern\n ${APP_NAME} --models \"github-copilot/*\"\n\n # Cycle models with fixed thinking levels\n ${APP_NAME} --models sonnet:high,haiku:low\n\n # Start with a specific thinking level\n ${APP_NAME} --thinking high \"Solve this complex problem\"\n\n # Read-only mode (no file modifications possible)\n ${APP_NAME} --tools read,grep,find,ls -p \"Review the code in src/\"\n\n # Export a session file to HTML\n ${APP_NAME} --export ~/${CONFIG_DIR_NAME}/agent/sessions/--path--/session.jsonl\n ${APP_NAME} --export session.jsonl output.html\n\n${chalk.bold(\"Environment Variables:\")}\n ANTHROPIC_API_KEY - Anthropic Claude API key\n ANTHROPIC_OAUTH_TOKEN - Anthropic OAuth token (alternative to API key)\n OPENAI_API_KEY - OpenAI GPT API key\n AZURE_OPENAI_API_KEY - Azure OpenAI API key\n AZURE_OPENAI_BASE_URL - Azure OpenAI base URL (https://{resource}.openai.azure.com/openai/v1)\n AZURE_OPENAI_RESOURCE_NAME - Azure OpenAI resource name (alternative to base URL)\n AZURE_OPENAI_API_VERSION - Azure OpenAI API version (default: v1)\n AZURE_OPENAI_DEPLOYMENT_NAME_MAP - Azure OpenAI model=deployment map (comma-separated)\n GEMINI_API_KEY - Google Gemini API key\n GROQ_API_KEY - Groq API key\n CEREBRAS_API_KEY - Cerebras API key\n XAI_API_KEY - xAI Grok API key\n OPENROUTER_API_KEY - OpenRouter API key\n AI_GATEWAY_API_KEY - Vercel AI Gateway API key\n ZAI_API_KEY - ZAI API key\n MISTRAL_API_KEY - Mistral API key\n MINIMAX_API_KEY - MiniMax API key\n OPENCODE_API_KEY - OpenCode Zen/OpenCode Go API key\n KIMI_API_KEY - Kimi For Coding API key\n AWS_PROFILE - AWS profile for Amazon Bedrock\n AWS_ACCESS_KEY_ID - AWS access key for Amazon Bedrock\n AWS_SECRET_ACCESS_KEY - AWS secret key for Amazon Bedrock\n AWS_BEARER_TOKEN_BEDROCK - Bedrock API key (bearer token)\n AWS_REGION - AWS region for Amazon Bedrock (e.g., us-east-1)\n ${ENV_AGENT_DIR.padEnd(32)} - Session storage directory (default: ~/${CONFIG_DIR_NAME}/agent)\n DRAHT_PACKAGE_DIR - Override package directory (for Nix/Guix store paths)\n DRAHT_OFFLINE - Disable startup network operations when set to 1/true/yes\n DRAHT_SHARE_VIEWER_URL - Base URL for /share command (default: https://draht.dev/session/)\n DRAHT_AI_ANTIGRAVITY_VERSION - Override Antigravity User-Agent version (e.g., 1.23.0)\n\n${chalk.bold(\"Available Tools (default: read, bash, edit, write):\")}\n read - Read file contents\n bash - Execute bash commands\n edit - Edit files with find/replace\n write - Write files (creates/overwrites)\n grep - Search file contents (read-only, off by default)\n find - Find files by glob pattern (read-only, off by default)\n ls - List directory contents (read-only, off by default)\n`);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGvD,OAAO,EAAY,KAAK,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAEjE,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;AAE3C,MAAM,WAAW,IAAI;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,sEAAsE;IACtE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,8EAA8E;IAC9E,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC,CAAC;CAC5C;AAID,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,aAAa,CAE1E;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,cAAc,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,SAAS,GAAG,QAAQ,CAAA;CAAE,CAAC,GAAG,IAAI,CAgI5G;AAED,wBAAgB,SAAS,IAAI,IAAI,CAwJhC","sourcesContent":["/**\n * CLI argument parsing and help display\n */\n\nimport type { ThinkingLevel } from \"@draht/agent-core\";\nimport chalk from \"chalk\";\nimport { APP_NAME, CONFIG_DIR_NAME, ENV_AGENT_DIR } from \"../config.js\";\nimport { allTools, type ToolName } from \"../core/tools/index.js\";\n\nexport type Mode = \"text\" | \"json\" | \"rpc\";\n\nexport interface Args {\n\tprovider?: string;\n\tmodel?: string;\n\tapiKey?: string;\n\tsystemPrompt?: string;\n\tappendSystemPrompt?: string;\n\tthinking?: ThinkingLevel;\n\tcontinue?: boolean;\n\tresume?: boolean;\n\thelp?: boolean;\n\tversion?: boolean;\n\tmode?: Mode;\n\tnoSession?: boolean;\n\tsession?: string;\n\tsessionDir?: string;\n\tmodels?: string[];\n\ttools?: ToolName[];\n\tnoTools?: boolean;\n\textensions?: string[];\n\tnoExtensions?: boolean;\n\tprint?: boolean;\n\texport?: string;\n\tnoSkills?: boolean;\n\tskills?: string[];\n\tpromptTemplates?: string[];\n\tnoPromptTemplates?: boolean;\n\tthemes?: string[];\n\tnoThemes?: boolean;\n\tlistModels?: string | true;\n\toffline?: boolean;\n\tverbose?: boolean;\n\t/** Experimental: Start session with socket server for multi-attach */\n\tattachable?: boolean;\n\t/** Experimental: Attach to an existing socket session */\n\tattach?: string;\n\t/** Experimental: List all attachable socket sessions */\n\tlistSessions?: boolean;\n\tmessages: string[];\n\tfileArgs: string[];\n\t/** Unknown flags (potentially extension flags) - map of flag name to value */\n\tunknownFlags: Map<string, boolean | string>;\n}\n\nconst VALID_THINKING_LEVELS = [\"off\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\"] as const;\n\nexport function isValidThinkingLevel(level: string): level is ThinkingLevel {\n\treturn VALID_THINKING_LEVELS.includes(level as ThinkingLevel);\n}\n\nexport function parseArgs(args: string[], extensionFlags?: Map<string, { type: \"boolean\" | \"string\" }>): Args {\n\tconst result: Args = {\n\t\tmessages: [],\n\t\tfileArgs: [],\n\t\tunknownFlags: new Map(),\n\t};\n\n\tfor (let i = 0; i < args.length; i++) {\n\t\tconst arg = args[i];\n\n\t\tif (arg === \"--help\" || arg === \"-h\") {\n\t\t\tresult.help = true;\n\t\t} else if (arg === \"--version\" || arg === \"-v\") {\n\t\t\tresult.version = true;\n\t\t} else if (arg === \"--mode\" && i + 1 < args.length) {\n\t\t\tconst mode = args[++i];\n\t\t\tif (mode === \"text\" || mode === \"json\" || mode === \"rpc\") {\n\t\t\t\tresult.mode = mode;\n\t\t\t}\n\t\t} else if (arg === \"--continue\" || arg === \"-c\") {\n\t\t\tresult.continue = true;\n\t\t} else if (arg === \"--resume\" || arg === \"-r\") {\n\t\t\tresult.resume = true;\n\t\t} else if (arg === \"--provider\" && i + 1 < args.length) {\n\t\t\tresult.provider = args[++i];\n\t\t} else if (arg === \"--model\" && i + 1 < args.length) {\n\t\t\tresult.model = args[++i];\n\t\t} else if (arg === \"--api-key\" && i + 1 < args.length) {\n\t\t\tresult.apiKey = args[++i];\n\t\t} else if (arg === \"--system-prompt\" && i + 1 < args.length) {\n\t\t\tresult.systemPrompt = args[++i];\n\t\t} else if (arg === \"--append-system-prompt\" && i + 1 < args.length) {\n\t\t\tresult.appendSystemPrompt = args[++i];\n\t\t} else if (arg === \"--no-session\") {\n\t\t\tresult.noSession = true;\n\t\t} else if (arg === \"--session\" && i + 1 < args.length) {\n\t\t\tresult.session = args[++i];\n\t\t} else if (arg === \"--session-dir\" && i + 1 < args.length) {\n\t\t\tresult.sessionDir = args[++i];\n\t\t} else if (arg === \"--models\" && i + 1 < args.length) {\n\t\t\tresult.models = args[++i].split(\",\").map((s) => s.trim());\n\t\t} else if (arg === \"--no-tools\") {\n\t\t\tresult.noTools = true;\n\t\t} else if (arg === \"--tools\" && i + 1 < args.length) {\n\t\t\tconst toolNames = args[++i].split(\",\").map((s) => s.trim());\n\t\t\tconst validTools: ToolName[] = [];\n\t\t\tfor (const name of toolNames) {\n\t\t\t\tif (name in allTools) {\n\t\t\t\t\tvalidTools.push(name as ToolName);\n\t\t\t\t} else {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\tchalk.yellow(`Warning: Unknown tool \"${name}\". Valid tools: ${Object.keys(allTools).join(\", \")}`),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tresult.tools = validTools;\n\t\t} else if (arg === \"--thinking\" && i + 1 < args.length) {\n\t\t\tconst level = args[++i];\n\t\t\tif (isValidThinkingLevel(level)) {\n\t\t\t\tresult.thinking = level;\n\t\t\t} else {\n\t\t\t\tconsole.error(\n\t\t\t\t\tchalk.yellow(\n\t\t\t\t\t\t`Warning: Invalid thinking level \"${level}\". Valid values: ${VALID_THINKING_LEVELS.join(\", \")}`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t} else if (arg === \"--print\" || arg === \"-p\") {\n\t\t\tresult.print = true;\n\t\t} else if (arg === \"--export\" && i + 1 < args.length) {\n\t\t\tresult.export = args[++i];\n\t\t} else if ((arg === \"--extension\" || arg === \"-e\") && i + 1 < args.length) {\n\t\t\tresult.extensions = result.extensions ?? [];\n\t\t\tresult.extensions.push(args[++i]);\n\t\t} else if (arg === \"--no-extensions\" || arg === \"-ne\") {\n\t\t\tresult.noExtensions = true;\n\t\t} else if (arg === \"--skill\" && i + 1 < args.length) {\n\t\t\tresult.skills = result.skills ?? [];\n\t\t\tresult.skills.push(args[++i]);\n\t\t} else if (arg === \"--prompt-template\" && i + 1 < args.length) {\n\t\t\tresult.promptTemplates = result.promptTemplates ?? [];\n\t\t\tresult.promptTemplates.push(args[++i]);\n\t\t} else if (arg === \"--theme\" && i + 1 < args.length) {\n\t\t\tresult.themes = result.themes ?? [];\n\t\t\tresult.themes.push(args[++i]);\n\t\t} else if (arg === \"--no-skills\" || arg === \"-ns\") {\n\t\t\tresult.noSkills = true;\n\t\t} else if (arg === \"--no-prompt-templates\" || arg === \"-np\") {\n\t\t\tresult.noPromptTemplates = true;\n\t\t} else if (arg === \"--no-themes\") {\n\t\t\tresult.noThemes = true;\n\t\t} else if (arg === \"--list-models\") {\n\t\t\t// Check if next arg is a search pattern (not a flag or file arg)\n\t\t\tif (i + 1 < args.length && !args[i + 1].startsWith(\"-\") && !args[i + 1].startsWith(\"@\")) {\n\t\t\t\tresult.listModels = args[++i];\n\t\t\t} else {\n\t\t\t\tresult.listModels = true;\n\t\t\t}\n\t\t} else if (arg === \"--verbose\") {\n\t\t\tresult.verbose = true;\n\t\t} else if (arg === \"--offline\") {\n\t\t\tresult.offline = true;\n\t\t} else if (arg === \"--attachable\") {\n\t\t\tresult.attachable = true;\n\t\t} else if (arg === \"--attach\" && i + 1 < args.length) {\n\t\t\tresult.attach = args[++i];\n\t\t} else if (arg === \"--list-sessions\") {\n\t\t\tresult.listSessions = true;\n\t\t} else if (arg.startsWith(\"@\")) {\n\t\t\tresult.fileArgs.push(arg.slice(1)); // Remove @ prefix\n\t\t} else if (arg.startsWith(\"--\") && extensionFlags) {\n\t\t\t// Check if it's an extension-registered flag\n\t\t\tconst flagName = arg.slice(2);\n\t\t\tconst extFlag = extensionFlags.get(flagName);\n\t\t\tif (extFlag) {\n\t\t\t\tif (extFlag.type === \"boolean\") {\n\t\t\t\t\tresult.unknownFlags.set(flagName, true);\n\t\t\t\t} else if (extFlag.type === \"string\" && i + 1 < args.length) {\n\t\t\t\t\tresult.unknownFlags.set(flagName, args[++i]);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Unknown flags without extensionFlags are silently ignored (first pass)\n\t\t} else if (!arg.startsWith(\"-\")) {\n\t\t\tresult.messages.push(arg);\n\t\t}\n\t}\n\n\treturn result;\n}\n\nexport function printHelp(): void {\n\tconsole.log(`${chalk.bold(APP_NAME)} - AI coding assistant with read, bash, edit, write tools\n\n${chalk.bold(\"Usage:\")}\n ${APP_NAME} [options] [@files...] [messages...]\n\n${chalk.bold(\"Commands:\")}\n ${APP_NAME} install <source> [-l] Install extension source and add to settings\n ${APP_NAME} remove <source> [-l] Remove extension source from settings\n ${APP_NAME} update [source] Update installed extensions (skips pinned sources)\n ${APP_NAME} list List installed extensions from settings\n ${APP_NAME} config Open TUI to enable/disable package resources\n ${APP_NAME} <command> --help Show help for install/remove/update/list\n\n${chalk.bold(\"Options:\")}\n --provider <name> Provider name (default: google)\n --model <pattern> Model pattern or ID (supports \"provider/id\" and optional \":<thinking>\")\n --api-key <key> API key (defaults to env vars)\n --system-prompt <text> System prompt (default: coding assistant prompt)\n --append-system-prompt <text> Append text or file contents to the system prompt\n --mode <mode> Output mode: text (default), json, or rpc\n --print, -p Non-interactive mode: process prompt and exit\n --continue, -c Continue previous session\n --resume, -r Select a session to resume\n --session <path> Use specific session file\n --session-dir <dir> Directory for session storage and lookup\n --no-session Don't save session (ephemeral)\n --models <patterns> Comma-separated model patterns for Ctrl+P cycling\n Supports globs (anthropic/*, *sonnet*) and fuzzy matching\n --no-tools Disable all built-in tools\n --tools <tools> Comma-separated list of tools to enable (default: read,bash,edit,write)\n Available: read, bash, edit, write, grep, find, ls\n --thinking <level> Set thinking level: off, minimal, low, medium, high, xhigh\n --extension, -e <path> Load an extension file (can be used multiple times)\n --no-extensions, -ne Disable extension discovery (explicit -e paths still work)\n --skill <path> Load a skill file or directory (can be used multiple times)\n --no-skills, -ns Disable skills discovery and loading\n --prompt-template <path> Load a prompt template file or directory (can be used multiple times)\n --no-prompt-templates, -np Disable prompt template discovery and loading\n --theme <path> Load a theme file or directory (can be used multiple times)\n --no-themes Disable theme discovery and loading\n --export <file> Export session file to HTML and exit\n --list-models [search] List available models (with optional fuzzy search)\n --verbose Force verbose startup (overrides quietStartup setting)\n --offline Disable startup network operations (same as DRAHT_OFFLINE=1)\n --help, -h Show this help\n --version, -v Show version number\n\n${chalk.bold(\"Experimental - Attachable Sessions (tmux-style multi-attach):\")}\n --attachable Start session with socket server for multi-client attachment\n --attach <session-id> Attach to an existing socket-based session\n --list-sessions List all running attachable sessions\n\nExtensions can register additional flags (e.g., --plan from plan-mode extension).\n\n${chalk.bold(\"Examples:\")}\n # Interactive mode\n ${APP_NAME}\n\n # Interactive mode with initial prompt\n ${APP_NAME} \"List all .ts files in src/\"\n\n # Include files in initial message\n ${APP_NAME} @prompt.md @image.png \"What color is the sky?\"\n\n # Non-interactive mode (process and exit)\n ${APP_NAME} -p \"List all .ts files in src/\"\n\n # Multiple messages (interactive)\n ${APP_NAME} \"Read package.json\" \"What dependencies do we have?\"\n\n # Continue previous session\n ${APP_NAME} --continue \"What did we discuss?\"\n\n # Use different model\n ${APP_NAME} --provider openai --model gpt-4o-mini \"Help me refactor this code\"\n\n # Use model with provider prefix (no --provider needed)\n ${APP_NAME} --model openai/gpt-4o \"Help me refactor this code\"\n\n # Use model with thinking level shorthand\n ${APP_NAME} --model sonnet:high \"Solve this complex problem\"\n\n # Limit model cycling to specific models\n ${APP_NAME} --models claude-sonnet,claude-haiku,gpt-4o\n\n # Limit to a specific provider with glob pattern\n ${APP_NAME} --models \"github-copilot/*\"\n\n # Cycle models with fixed thinking levels\n ${APP_NAME} --models sonnet:high,haiku:low\n\n # Start with a specific thinking level\n ${APP_NAME} --thinking high \"Solve this complex problem\"\n\n # Read-only mode (no file modifications possible)\n ${APP_NAME} --tools read,grep,find,ls -p \"Review the code in src/\"\n\n # Export a session file to HTML\n ${APP_NAME} --export ~/${CONFIG_DIR_NAME}/agent/sessions/--path--/session.jsonl\n ${APP_NAME} --export session.jsonl output.html\n\n # ${chalk.bold(\"Experimental - Attachable Sessions\")}\n # Start an attachable session (others can attach via --attach)\n ${APP_NAME} --attachable \"Build a new feature\"\n\n # List all running attachable sessions\n ${APP_NAME} --list-sessions\n\n # Attach to a running session (tmux-style surveillance)\n ${APP_NAME} --attach abc-123-session-id\n\n${chalk.bold(\"Environment Variables:\")}\n ANTHROPIC_API_KEY - Anthropic Claude API key\n ANTHROPIC_OAUTH_TOKEN - Anthropic OAuth token (alternative to API key)\n OPENAI_API_KEY - OpenAI GPT API key\n AZURE_OPENAI_API_KEY - Azure OpenAI API key\n AZURE_OPENAI_BASE_URL - Azure OpenAI base URL (https://{resource}.openai.azure.com/openai/v1)\n AZURE_OPENAI_RESOURCE_NAME - Azure OpenAI resource name (alternative to base URL)\n AZURE_OPENAI_API_VERSION - Azure OpenAI API version (default: v1)\n AZURE_OPENAI_DEPLOYMENT_NAME_MAP - Azure OpenAI model=deployment map (comma-separated)\n GEMINI_API_KEY - Google Gemini API key\n GROQ_API_KEY - Groq API key\n CEREBRAS_API_KEY - Cerebras API key\n XAI_API_KEY - xAI Grok API key\n OPENROUTER_API_KEY - OpenRouter API key\n AI_GATEWAY_API_KEY - Vercel AI Gateway API key\n ZAI_API_KEY - ZAI API key\n MISTRAL_API_KEY - Mistral API key\n MINIMAX_API_KEY - MiniMax API key\n OPENCODE_API_KEY - OpenCode Zen/OpenCode Go API key\n KIMI_API_KEY - Kimi For Coding API key\n AWS_PROFILE - AWS profile for Amazon Bedrock\n AWS_ACCESS_KEY_ID - AWS access key for Amazon Bedrock\n AWS_SECRET_ACCESS_KEY - AWS secret key for Amazon Bedrock\n AWS_BEARER_TOKEN_BEDROCK - Bedrock API key (bearer token)\n AWS_REGION - AWS region for Amazon Bedrock (e.g., us-east-1)\n ${ENV_AGENT_DIR.padEnd(32)} - Session storage directory (default: ~/${CONFIG_DIR_NAME}/agent)\n DRAHT_PACKAGE_DIR - Override package directory (for Nix/Guix store paths)\n DRAHT_OFFLINE - Disable startup network operations when set to 1/true/yes\n DRAHT_SHARE_VIEWER_URL - Base URL for /share command (default: https://draht.dev/session/)\n DRAHT_AI_ANTIGRAVITY_VERSION - Override Antigravity User-Agent version (e.g., 1.23.0)\n\n${chalk.bold(\"Available Tools (default: read, bash, edit, write):\")}\n read - Read file contents\n bash - Execute bash commands\n edit - Edit files with find/replace\n write - Write files (creates/overwrites)\n grep - Search file contents (read-only, off by default)\n find - Find files by glob pattern (read-only, off by default)\n ls - List directory contents (read-only, off by default)\n`);\n}\n"]}
|
package/dist/cli/args.js
CHANGED
|
@@ -135,6 +135,15 @@ export function parseArgs(args, extensionFlags) {
|
|
|
135
135
|
else if (arg === "--offline") {
|
|
136
136
|
result.offline = true;
|
|
137
137
|
}
|
|
138
|
+
else if (arg === "--attachable") {
|
|
139
|
+
result.attachable = true;
|
|
140
|
+
}
|
|
141
|
+
else if (arg === "--attach" && i + 1 < args.length) {
|
|
142
|
+
result.attach = args[++i];
|
|
143
|
+
}
|
|
144
|
+
else if (arg === "--list-sessions") {
|
|
145
|
+
result.listSessions = true;
|
|
146
|
+
}
|
|
138
147
|
else if (arg.startsWith("@")) {
|
|
139
148
|
result.fileArgs.push(arg.slice(1)); // Remove @ prefix
|
|
140
149
|
}
|
|
@@ -206,6 +215,11 @@ ${chalk.bold("Options:")}
|
|
|
206
215
|
--help, -h Show this help
|
|
207
216
|
--version, -v Show version number
|
|
208
217
|
|
|
218
|
+
${chalk.bold("Experimental - Attachable Sessions (tmux-style multi-attach):")}
|
|
219
|
+
--attachable Start session with socket server for multi-client attachment
|
|
220
|
+
--attach <session-id> Attach to an existing socket-based session
|
|
221
|
+
--list-sessions List all running attachable sessions
|
|
222
|
+
|
|
209
223
|
Extensions can register additional flags (e.g., --plan from plan-mode extension).
|
|
210
224
|
|
|
211
225
|
${chalk.bold("Examples:")}
|
|
@@ -255,6 +269,16 @@ ${chalk.bold("Examples:")}
|
|
|
255
269
|
${APP_NAME} --export ~/${CONFIG_DIR_NAME}/agent/sessions/--path--/session.jsonl
|
|
256
270
|
${APP_NAME} --export session.jsonl output.html
|
|
257
271
|
|
|
272
|
+
# ${chalk.bold("Experimental - Attachable Sessions")}
|
|
273
|
+
# Start an attachable session (others can attach via --attach)
|
|
274
|
+
${APP_NAME} --attachable "Build a new feature"
|
|
275
|
+
|
|
276
|
+
# List all running attachable sessions
|
|
277
|
+
${APP_NAME} --list-sessions
|
|
278
|
+
|
|
279
|
+
# Attach to a running session (tmux-style surveillance)
|
|
280
|
+
${APP_NAME} --attach abc-123-session-id
|
|
281
|
+
|
|
258
282
|
${chalk.bold("Environment Variables:")}
|
|
259
283
|
ANTHROPIC_API_KEY - Anthropic Claude API key
|
|
260
284
|
ANTHROPIC_OAUTH_TOKEN - Anthropic OAuth token (alternative to API key)
|