@hypercli/hq 0.2.3 → 0.4.0
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/README.md +2 -1
- package/dist/commands/hq/attach.d.ts.map +1 -1
- package/dist/commands/hq/attach.js +8 -3
- package/dist/commands/hq/attach.js.map +1 -1
- package/dist/commands/hq/launch.d.ts +19 -0
- package/dist/commands/hq/launch.d.ts.map +1 -0
- package/dist/commands/hq/launch.js +155 -0
- package/dist/commands/hq/launch.js.map +1 -0
- package/dist/commands/hq/relaunch.d.ts +18 -0
- package/dist/commands/hq/relaunch.d.ts.map +1 -0
- package/dist/commands/hq/relaunch.js +124 -0
- package/dist/commands/hq/relaunch.js.map +1 -0
- package/dist/commands/hq/start.d.ts.map +1 -1
- package/dist/commands/hq/start.js +54 -18
- package/dist/commands/hq/start.js.map +1 -1
- package/dist/commands/hq/stop-all.d.ts.map +1 -1
- package/dist/commands/hq/stop-all.js +2 -0
- package/dist/commands/hq/stop-all.js.map +1 -1
- package/dist/commands/hq/stop.d.ts.map +1 -1
- package/dist/commands/hq/stop.js +9 -3
- package/dist/commands/hq/stop.js.map +1 -1
- package/dist/commands/hq/web.d.ts +7 -0
- package/dist/commands/hq/web.d.ts.map +1 -0
- package/dist/commands/hq/web.js +45 -0
- package/dist/commands/hq/web.js.map +1 -0
- package/dist/config/schema.d.ts +1 -1
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/setup.d.ts +4 -0
- package/dist/config/setup.d.ts.map +1 -0
- package/dist/config/setup.js +148 -0
- package/dist/config/setup.js.map +1 -0
- package/dist/services/claude.d.ts +16 -8
- package/dist/services/claude.d.ts.map +1 -1
- package/dist/services/claude.js +17 -9
- package/dist/services/claude.js.map +1 -1
- package/dist/services/sessions.d.ts +19 -0
- package/dist/services/sessions.d.ts.map +1 -0
- package/dist/services/sessions.js +51 -0
- package/dist/services/sessions.js.map +1 -0
- package/dist/services/tmux.d.ts +5 -0
- package/dist/services/tmux.d.ts.map +1 -1
- package/dist/services/tmux.js +13 -0
- package/dist/services/tmux.js.map +1 -1
- package/dist/utils/banner.d.ts.map +1 -1
- package/dist/utils/banner.js +2 -1
- package/dist/utils/banner.js.map +1 -1
- package/dist/utils/paths.d.ts +2 -0
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +2 -0
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/trust.d.ts +10 -0
- package/dist/utils/trust.d.ts.map +1 -0
- package/dist/utils/trust.js +41 -0
- package/dist/utils/trust.js.map +1 -0
- package/help/hq.md +6 -5
- package/oclif.manifest.json +153 -64
- package/package.json +3 -3
- package/dist/commands/hq/spawn.d.ts +0 -21
- package/dist/commands/hq/spawn.d.ts.map +0 -1
- package/dist/commands/hq/spawn.js +0 -124
- package/dist/commands/hq/spawn.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trust.d.ts","sourceRoot":"","sources":["../../src/utils/trust.ts"],"names":[],"mappings":"AAoBA;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAUvD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAMhD"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { dirname, resolve } from "node:path";
|
|
4
|
+
const CLAUDE_JSON_PATH = resolve(homedir(), ".claude.json");
|
|
5
|
+
function readClaudeJson() {
|
|
6
|
+
if (!existsSync(CLAUDE_JSON_PATH))
|
|
7
|
+
return {};
|
|
8
|
+
return JSON.parse(readFileSync(CLAUDE_JSON_PATH, "utf-8"));
|
|
9
|
+
}
|
|
10
|
+
function writeClaudeJson(data) {
|
|
11
|
+
writeFileSync(CLAUDE_JSON_PATH, JSON.stringify(data, null, 2), "utf-8");
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Check if a directory (or any ancestor) is trusted by Claude Code.
|
|
15
|
+
* Trust is stored in ~/.claude.json under projects[path].hasTrustDialogAccepted.
|
|
16
|
+
*/
|
|
17
|
+
export function isWorkspaceTrusted(dir) {
|
|
18
|
+
const data = readClaudeJson();
|
|
19
|
+
if (!data.projects)
|
|
20
|
+
return false;
|
|
21
|
+
let current = dir;
|
|
22
|
+
while (current !== "/") {
|
|
23
|
+
if (data.projects[current]?.hasTrustDialogAccepted === true)
|
|
24
|
+
return true;
|
|
25
|
+
current = dirname(current);
|
|
26
|
+
}
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Trust a directory for Claude Code by setting hasTrustDialogAccepted in ~/.claude.json.
|
|
31
|
+
*/
|
|
32
|
+
export function trustWorkspace(dir) {
|
|
33
|
+
const data = readClaudeJson();
|
|
34
|
+
if (!data.projects)
|
|
35
|
+
data.projects = {};
|
|
36
|
+
if (!data.projects[dir])
|
|
37
|
+
data.projects[dir] = {};
|
|
38
|
+
data.projects[dir].hasTrustDialogAccepted = true;
|
|
39
|
+
writeClaudeJson(data);
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=trust.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trust.js","sourceRoot":"","sources":["../../src/utils/trust.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE7C,MAAM,gBAAgB,GAAG,OAAO,CAAC,OAAO,EAAE,EAAE,cAAc,CAAC,CAAC;AAO5D,SAAS,cAAc;IACtB,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC;QAAE,OAAO,EAAE,CAAC;IAC7C,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED,SAAS,eAAe,CAAC,IAAgB;IACxC,aAAa,CAAC,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AACzE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAW;IAC7C,MAAM,IAAI,GAAG,cAAc,EAAE,CAAC;IAC9B,IAAI,CAAC,IAAI,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAC;IAEjC,IAAI,OAAO,GAAG,GAAG,CAAC;IAClB,OAAO,OAAO,KAAK,GAAG,EAAE,CAAC;QACxB,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,sBAAsB,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QACzE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW;IACzC,MAAM,IAAI,GAAG,cAAc,EAAE,CAAC;IAC9B,IAAI,CAAC,IAAI,CAAC,QAAQ;QAAE,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;IACvC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;IACjD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,sBAAsB,GAAG,IAAI,CAAC;IACjD,eAAe,CAAC,IAAI,CAAC,CAAC;AACvB,CAAC"}
|
package/help/hq.md
CHANGED
|
@@ -15,8 +15,9 @@ Always-on Claude Code command center. Manages persistent Claude sessions via tmu
|
|
|
15
15
|
| `hyper hq stop [session]` | Stop an HQ session |
|
|
16
16
|
| `hyper hq stop-all` | Stop all HQ-managed sessions |
|
|
17
17
|
| `hyper hq attach [session]` | Attach to an HQ tmux session |
|
|
18
|
-
| `hyper hq
|
|
19
|
-
| `hyper hq
|
|
18
|
+
| `hyper hq launch [project] [path]` | Launch a Claude session for a project |
|
|
19
|
+
| `hyper hq relaunch <session\|project>` | Relaunch a session with --continue |
|
|
20
|
+
| `hyper hq list` | List available projects |
|
|
20
21
|
| `hyper hq status` | Show running HQ sessions |
|
|
21
22
|
| `hyper hq config` | Show HQ configuration |
|
|
22
23
|
|
|
@@ -32,8 +33,8 @@ hyper hq start
|
|
|
32
33
|
# 3. Check what projects are available
|
|
33
34
|
hyper hq list
|
|
34
35
|
|
|
35
|
-
# 4.
|
|
36
|
-
hyper hq
|
|
36
|
+
# 4. Launch a Claude session for a project
|
|
37
|
+
hyper hq launch my-project
|
|
37
38
|
|
|
38
39
|
# 5. Check running sessions
|
|
39
40
|
hyper hq status
|
|
@@ -47,6 +48,6 @@ hyper hq stop-all
|
|
|
47
48
|
|
|
48
49
|
## How It Works
|
|
49
50
|
|
|
50
|
-
HQ runs a persistent Claude Code instance in a tmux session in remote-control server mode. Once started, you can connect to it from claude.ai/code, the Claude mobile app, or via Telegram. From there, you can ask HQ to
|
|
51
|
+
HQ runs a persistent Claude Code instance in a tmux session in remote-control server mode. Once started, you can connect to it from claude.ai/code, the Claude mobile app, or via Telegram. From there, you can ask HQ to launch sessions for any of your projects.
|
|
51
52
|
|
|
52
53
|
Run `hyper hq <command> --help` for details on any command.
|
package/oclif.manifest.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"aliases": [],
|
|
5
5
|
"args": {
|
|
6
6
|
"session": {
|
|
7
|
-
"description": "Session name or project name (default:
|
|
7
|
+
"description": "Session name or project name (default: HQ session from config)",
|
|
8
8
|
"name": "session",
|
|
9
9
|
"required": false
|
|
10
10
|
}
|
|
@@ -85,14 +85,32 @@
|
|
|
85
85
|
"config.js"
|
|
86
86
|
]
|
|
87
87
|
},
|
|
88
|
-
"hq:
|
|
88
|
+
"hq:launch": {
|
|
89
89
|
"aliases": [],
|
|
90
|
-
"args": {
|
|
91
|
-
|
|
90
|
+
"args": {
|
|
91
|
+
"project": {
|
|
92
|
+
"description": "Project name (under projects root) or absolute path",
|
|
93
|
+
"name": "project",
|
|
94
|
+
"required": false
|
|
95
|
+
},
|
|
96
|
+
"path": {
|
|
97
|
+
"description": "Relative path inside the project to use as working directory",
|
|
98
|
+
"name": "path",
|
|
99
|
+
"required": false
|
|
100
|
+
},
|
|
101
|
+
"session-name": {
|
|
102
|
+
"description": "Custom session name (default: hq-<project>-MM-DD-HH-mm)",
|
|
103
|
+
"name": "session-name",
|
|
104
|
+
"required": false
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
"description": "Launch a Claude session for a project",
|
|
92
108
|
"examples": [
|
|
93
|
-
"<%= config.bin %> hq
|
|
94
|
-
"<%= config.bin %> hq
|
|
95
|
-
"<%= config.bin %> hq
|
|
109
|
+
"<%= config.bin %> hq launch my-project",
|
|
110
|
+
"<%= config.bin %> hq launch my-project src/frontend",
|
|
111
|
+
"<%= config.bin %> hq launch my-project src/frontend my-session",
|
|
112
|
+
"<%= config.bin %> hq launch my-project --yolo",
|
|
113
|
+
"<%= config.bin %> hq launch"
|
|
96
114
|
],
|
|
97
115
|
"flags": {
|
|
98
116
|
"debug": {
|
|
@@ -102,42 +120,57 @@
|
|
|
102
120
|
"allowNo": false,
|
|
103
121
|
"type": "boolean"
|
|
104
122
|
},
|
|
105
|
-
"
|
|
106
|
-
"description": "
|
|
107
|
-
"name": "
|
|
123
|
+
"permission-mode": {
|
|
124
|
+
"description": "Permission mode",
|
|
125
|
+
"name": "permission-mode",
|
|
108
126
|
"hasDynamicHelp": false,
|
|
109
127
|
"multiple": false,
|
|
128
|
+
"options": [
|
|
129
|
+
"default",
|
|
130
|
+
"acceptEdits",
|
|
131
|
+
"plan",
|
|
132
|
+
"bypassPermissions",
|
|
133
|
+
"auto"
|
|
134
|
+
],
|
|
110
135
|
"type": "option"
|
|
111
136
|
},
|
|
112
|
-
"
|
|
113
|
-
"description": "
|
|
114
|
-
"name": "
|
|
137
|
+
"yolo": {
|
|
138
|
+
"description": "Skip all permission checks (sets --permission-mode bypassPermissions)",
|
|
139
|
+
"name": "yolo",
|
|
115
140
|
"allowNo": false,
|
|
116
141
|
"type": "boolean"
|
|
142
|
+
},
|
|
143
|
+
"telegram": {
|
|
144
|
+
"description": "Enable Telegram channel (enabled by default when configured)",
|
|
145
|
+
"name": "telegram",
|
|
146
|
+
"allowNo": true,
|
|
147
|
+
"type": "boolean"
|
|
117
148
|
}
|
|
118
149
|
},
|
|
119
150
|
"hasDynamicHelp": false,
|
|
120
151
|
"hiddenAliases": [],
|
|
121
|
-
"id": "hq:
|
|
152
|
+
"id": "hq:launch",
|
|
122
153
|
"pluginAlias": "@hypercli/hq",
|
|
123
154
|
"pluginName": "@hypercli/hq",
|
|
124
155
|
"pluginType": "core",
|
|
125
|
-
"strict":
|
|
156
|
+
"strict": false,
|
|
126
157
|
"enableJsonFlag": false,
|
|
127
158
|
"isESM": true,
|
|
128
159
|
"relativePath": [
|
|
129
160
|
"dist",
|
|
130
161
|
"commands",
|
|
131
162
|
"hq",
|
|
132
|
-
"
|
|
163
|
+
"launch.js"
|
|
133
164
|
]
|
|
134
165
|
},
|
|
135
|
-
"hq:
|
|
166
|
+
"hq:list": {
|
|
136
167
|
"aliases": [],
|
|
137
168
|
"args": {},
|
|
138
|
-
"description": "
|
|
169
|
+
"description": "List available projects and their worktrees",
|
|
139
170
|
"examples": [
|
|
140
|
-
"<%= config.bin %> hq
|
|
171
|
+
"<%= config.bin %> hq list",
|
|
172
|
+
"<%= config.bin %> hq list --json",
|
|
173
|
+
"<%= config.bin %> hq list --root /path/to/projects"
|
|
141
174
|
],
|
|
142
175
|
"flags": {
|
|
143
176
|
"debug": {
|
|
@@ -146,11 +179,24 @@
|
|
|
146
179
|
"name": "debug",
|
|
147
180
|
"allowNo": false,
|
|
148
181
|
"type": "boolean"
|
|
182
|
+
},
|
|
183
|
+
"root": {
|
|
184
|
+
"description": "Override projects root directory",
|
|
185
|
+
"name": "root",
|
|
186
|
+
"hasDynamicHelp": false,
|
|
187
|
+
"multiple": false,
|
|
188
|
+
"type": "option"
|
|
189
|
+
},
|
|
190
|
+
"json": {
|
|
191
|
+
"description": "Output as JSON",
|
|
192
|
+
"name": "json",
|
|
193
|
+
"allowNo": false,
|
|
194
|
+
"type": "boolean"
|
|
149
195
|
}
|
|
150
196
|
},
|
|
151
197
|
"hasDynamicHelp": false,
|
|
152
198
|
"hiddenAliases": [],
|
|
153
|
-
"id": "hq:
|
|
199
|
+
"id": "hq:list",
|
|
154
200
|
"pluginAlias": "@hypercli/hq",
|
|
155
201
|
"pluginName": "@hypercli/hq",
|
|
156
202
|
"pluginType": "core",
|
|
@@ -161,25 +207,29 @@
|
|
|
161
207
|
"dist",
|
|
162
208
|
"commands",
|
|
163
209
|
"hq",
|
|
164
|
-
"
|
|
210
|
+
"list.js"
|
|
165
211
|
]
|
|
166
212
|
},
|
|
167
|
-
"hq:
|
|
213
|
+
"hq:relaunch": {
|
|
168
214
|
"aliases": [],
|
|
169
215
|
"args": {
|
|
170
|
-
"
|
|
171
|
-
"description": "
|
|
172
|
-
"name": "
|
|
216
|
+
"target": {
|
|
217
|
+
"description": "Session name, or project name",
|
|
218
|
+
"name": "target",
|
|
173
219
|
"required": true
|
|
220
|
+
},
|
|
221
|
+
"path": {
|
|
222
|
+
"description": "Relative path inside the project (when target is a project name)",
|
|
223
|
+
"name": "path",
|
|
224
|
+
"required": false
|
|
174
225
|
}
|
|
175
226
|
},
|
|
176
|
-
"description": "
|
|
227
|
+
"description": "Stop and relaunch a session with --continue",
|
|
177
228
|
"examples": [
|
|
178
|
-
"<%= config.bin %> hq
|
|
179
|
-
"<%= config.bin %> hq
|
|
180
|
-
"<%= config.bin %> hq
|
|
181
|
-
"<%= config.bin %> hq
|
|
182
|
-
"<%= config.bin %> hq spawn my-project -- --dangerously-skip-permissions"
|
|
229
|
+
"<%= config.bin %> hq relaunch hq-my-project-03-24-10-30",
|
|
230
|
+
"<%= config.bin %> hq relaunch my-project",
|
|
231
|
+
"<%= config.bin %> hq relaunch my-project src/frontend",
|
|
232
|
+
"<%= config.bin %> hq relaunch hq-my-project-03-24-10-30 --yolo"
|
|
183
233
|
],
|
|
184
234
|
"flags": {
|
|
185
235
|
"debug": {
|
|
@@ -189,20 +239,6 @@
|
|
|
189
239
|
"allowNo": false,
|
|
190
240
|
"type": "boolean"
|
|
191
241
|
},
|
|
192
|
-
"worktree": {
|
|
193
|
-
"description": "Use an existing worktree (branch name)",
|
|
194
|
-
"name": "worktree",
|
|
195
|
-
"hasDynamicHelp": false,
|
|
196
|
-
"multiple": false,
|
|
197
|
-
"type": "option"
|
|
198
|
-
},
|
|
199
|
-
"new-worktree": {
|
|
200
|
-
"description": "Create a new worktree via wt switch -c",
|
|
201
|
-
"name": "new-worktree",
|
|
202
|
-
"hasDynamicHelp": false,
|
|
203
|
-
"multiple": false,
|
|
204
|
-
"type": "option"
|
|
205
|
-
},
|
|
206
242
|
"permission-mode": {
|
|
207
243
|
"description": "Permission mode",
|
|
208
244
|
"name": "permission-mode",
|
|
@@ -212,25 +248,13 @@
|
|
|
212
248
|
"default",
|
|
213
249
|
"acceptEdits",
|
|
214
250
|
"plan",
|
|
251
|
+
"bypassPermissions",
|
|
215
252
|
"auto"
|
|
216
253
|
],
|
|
217
254
|
"type": "option"
|
|
218
255
|
},
|
|
219
|
-
"name": {
|
|
220
|
-
"description": "Custom session name",
|
|
221
|
-
"name": "name",
|
|
222
|
-
"hasDynamicHelp": false,
|
|
223
|
-
"multiple": false,
|
|
224
|
-
"type": "option"
|
|
225
|
-
},
|
|
226
|
-
"resume": {
|
|
227
|
-
"description": "Resume the previous session for this project",
|
|
228
|
-
"name": "resume",
|
|
229
|
-
"allowNo": false,
|
|
230
|
-
"type": "boolean"
|
|
231
|
-
},
|
|
232
256
|
"yolo": {
|
|
233
|
-
"description": "Skip all permission checks (
|
|
257
|
+
"description": "Skip all permission checks (sets --permission-mode bypassPermissions)",
|
|
234
258
|
"name": "yolo",
|
|
235
259
|
"allowNo": false,
|
|
236
260
|
"type": "boolean"
|
|
@@ -244,7 +268,7 @@
|
|
|
244
268
|
},
|
|
245
269
|
"hasDynamicHelp": false,
|
|
246
270
|
"hiddenAliases": [],
|
|
247
|
-
"id": "hq:
|
|
271
|
+
"id": "hq:relaunch",
|
|
248
272
|
"pluginAlias": "@hypercli/hq",
|
|
249
273
|
"pluginName": "@hypercli/hq",
|
|
250
274
|
"pluginType": "core",
|
|
@@ -255,7 +279,39 @@
|
|
|
255
279
|
"dist",
|
|
256
280
|
"commands",
|
|
257
281
|
"hq",
|
|
258
|
-
"
|
|
282
|
+
"relaunch.js"
|
|
283
|
+
]
|
|
284
|
+
},
|
|
285
|
+
"hq:setup": {
|
|
286
|
+
"aliases": [],
|
|
287
|
+
"args": {},
|
|
288
|
+
"description": "Set up HQ — configure settings",
|
|
289
|
+
"examples": [
|
|
290
|
+
"<%= config.bin %> hq setup"
|
|
291
|
+
],
|
|
292
|
+
"flags": {
|
|
293
|
+
"debug": {
|
|
294
|
+
"char": "d",
|
|
295
|
+
"description": "Enable debug output",
|
|
296
|
+
"name": "debug",
|
|
297
|
+
"allowNo": false,
|
|
298
|
+
"type": "boolean"
|
|
299
|
+
}
|
|
300
|
+
},
|
|
301
|
+
"hasDynamicHelp": false,
|
|
302
|
+
"hiddenAliases": [],
|
|
303
|
+
"id": "hq:setup",
|
|
304
|
+
"pluginAlias": "@hypercli/hq",
|
|
305
|
+
"pluginName": "@hypercli/hq",
|
|
306
|
+
"pluginType": "core",
|
|
307
|
+
"strict": true,
|
|
308
|
+
"enableJsonFlag": false,
|
|
309
|
+
"isESM": true,
|
|
310
|
+
"relativePath": [
|
|
311
|
+
"dist",
|
|
312
|
+
"commands",
|
|
313
|
+
"hq",
|
|
314
|
+
"setup.js"
|
|
259
315
|
]
|
|
260
316
|
},
|
|
261
317
|
"hq:start": {
|
|
@@ -291,7 +347,7 @@
|
|
|
291
347
|
"type": "boolean"
|
|
292
348
|
},
|
|
293
349
|
"yolo": {
|
|
294
|
-
"description": "Skip
|
|
350
|
+
"description": "Skip permission checks — HQ runs autonomously on startup",
|
|
295
351
|
"name": "yolo",
|
|
296
352
|
"allowNo": false,
|
|
297
353
|
"type": "boolean"
|
|
@@ -305,6 +361,7 @@
|
|
|
305
361
|
"default",
|
|
306
362
|
"acceptEdits",
|
|
307
363
|
"plan",
|
|
364
|
+
"bypassPermissions",
|
|
308
365
|
"auto"
|
|
309
366
|
],
|
|
310
367
|
"type": "option"
|
|
@@ -407,7 +464,7 @@
|
|
|
407
464
|
"aliases": [],
|
|
408
465
|
"args": {
|
|
409
466
|
"session": {
|
|
410
|
-
"description": "Session name or project name (default:
|
|
467
|
+
"description": "Session name or project name (default: HQ session from config)",
|
|
411
468
|
"name": "session",
|
|
412
469
|
"required": false
|
|
413
470
|
}
|
|
@@ -442,6 +499,38 @@
|
|
|
442
499
|
"stop.js"
|
|
443
500
|
]
|
|
444
501
|
},
|
|
502
|
+
"hq:web": {
|
|
503
|
+
"aliases": [],
|
|
504
|
+
"args": {},
|
|
505
|
+
"description": "Open the HQ session in claude.ai/code (requires /remote-control to be active)",
|
|
506
|
+
"examples": [
|
|
507
|
+
"<%= config.bin %> hq web"
|
|
508
|
+
],
|
|
509
|
+
"flags": {
|
|
510
|
+
"debug": {
|
|
511
|
+
"char": "d",
|
|
512
|
+
"description": "Enable debug output",
|
|
513
|
+
"name": "debug",
|
|
514
|
+
"allowNo": false,
|
|
515
|
+
"type": "boolean"
|
|
516
|
+
}
|
|
517
|
+
},
|
|
518
|
+
"hasDynamicHelp": false,
|
|
519
|
+
"hiddenAliases": [],
|
|
520
|
+
"id": "hq:web",
|
|
521
|
+
"pluginAlias": "@hypercli/hq",
|
|
522
|
+
"pluginName": "@hypercli/hq",
|
|
523
|
+
"pluginType": "core",
|
|
524
|
+
"strict": true,
|
|
525
|
+
"enableJsonFlag": false,
|
|
526
|
+
"isESM": true,
|
|
527
|
+
"relativePath": [
|
|
528
|
+
"dist",
|
|
529
|
+
"commands",
|
|
530
|
+
"hq",
|
|
531
|
+
"web.js"
|
|
532
|
+
]
|
|
533
|
+
},
|
|
445
534
|
"hq:configure:telegram": {
|
|
446
535
|
"aliases": [],
|
|
447
536
|
"args": {},
|
|
@@ -476,5 +565,5 @@
|
|
|
476
565
|
]
|
|
477
566
|
}
|
|
478
567
|
},
|
|
479
|
-
"version": "0.
|
|
568
|
+
"version": "0.4.0"
|
|
480
569
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hypercli/hq",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Claude Code session management for HyperDev — always-on control plane",
|
|
6
6
|
"keywords": [
|
|
@@ -74,9 +74,9 @@
|
|
|
74
74
|
},
|
|
75
75
|
"dependencies": {
|
|
76
76
|
"@clack/prompts": "^1.1.0",
|
|
77
|
-
"@hypercli/ui": "^0.
|
|
77
|
+
"@hypercli/ui": "^0.4.0",
|
|
78
78
|
"@oclif/core": "^4",
|
|
79
|
-
"create-hyper-hq": "^0.
|
|
79
|
+
"create-hyper-hq": "^0.4.0",
|
|
80
80
|
"smol-toml": "^1"
|
|
81
81
|
},
|
|
82
82
|
"devDependencies": {
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { BaseCommand } from "#lib/base-command";
|
|
2
|
-
export default class Spawn extends BaseCommand<typeof Spawn> {
|
|
3
|
-
static description: string;
|
|
4
|
-
static examples: string[];
|
|
5
|
-
static args: {
|
|
6
|
-
project: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
7
|
-
};
|
|
8
|
-
static strict: boolean;
|
|
9
|
-
static flags: {
|
|
10
|
-
worktree: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
-
"new-worktree": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
-
"permission-mode": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
-
name: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
-
resume: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
15
|
-
yolo: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
16
|
-
telegram: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
17
|
-
debug: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
18
|
-
};
|
|
19
|
-
run(): Promise<void>;
|
|
20
|
-
}
|
|
21
|
-
//# sourceMappingURL=spawn.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"spawn.d.ts","sourceRoot":"","sources":["../../../src/commands/hq/spawn.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAShD,MAAM,CAAC,OAAO,OAAO,KAAM,SAAQ,WAAW,CAAC,OAAO,KAAK,CAAC;IAC3D,OAAgB,WAAW,SAA8C;IAEzE,OAAgB,QAAQ,WAMtB;IAEF,OAAgB,IAAI;;MAKlB;IAGF,OAAgB,MAAM,UAAS;IAE/B,OAAgB,KAAK;;;;;;;;;MAsBnB;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAuF1B"}
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
import { existsSync, mkdirSync } from "node:fs";
|
|
2
|
-
import { basename, resolve } from "node:path";
|
|
3
|
-
import { Args, Flags } from "@oclif/core";
|
|
4
|
-
import { loadConfig } from "#config/index";
|
|
5
|
-
import { BaseCommand } from "#lib/base-command";
|
|
6
|
-
import { buildClaudeCommand } from "#services/claude";
|
|
7
|
-
import { createWorktree, findWorktreePath, resolveProjectDir } from "#services/projects";
|
|
8
|
-
import { getProjectTelegramEnv, TELEGRAM_CHANNEL_PLUGIN } from "#services/telegram";
|
|
9
|
-
import * as tmux from "#services/tmux";
|
|
10
|
-
import { sanitizeSessionName } from "#services/tmux";
|
|
11
|
-
import { log } from "#utils/log";
|
|
12
|
-
import { LOG_DIR } from "#utils/paths";
|
|
13
|
-
export default class Spawn extends BaseCommand {
|
|
14
|
-
static description = "Spawn a new Claude session for a project";
|
|
15
|
-
static examples = [
|
|
16
|
-
"<%= config.bin %> hq spawn my-project",
|
|
17
|
-
"<%= config.bin %> hq spawn my-project --worktree feat-auth",
|
|
18
|
-
"<%= config.bin %> hq spawn my-project --new-worktree feat-login",
|
|
19
|
-
"<%= config.bin %> hq spawn /absolute/path/to/project",
|
|
20
|
-
"<%= config.bin %> hq spawn my-project -- --dangerously-skip-permissions",
|
|
21
|
-
];
|
|
22
|
-
static args = {
|
|
23
|
-
project: Args.string({
|
|
24
|
-
description: "Project name (under projects root) or absolute path",
|
|
25
|
-
required: true,
|
|
26
|
-
}),
|
|
27
|
-
};
|
|
28
|
-
// Allow extra args after -- to pass through to claude
|
|
29
|
-
static strict = false;
|
|
30
|
-
static flags = {
|
|
31
|
-
...BaseCommand.baseFlags,
|
|
32
|
-
worktree: Flags.string({ description: "Use an existing worktree (branch name)" }),
|
|
33
|
-
"new-worktree": Flags.string({ description: "Create a new worktree via wt switch -c" }),
|
|
34
|
-
"permission-mode": Flags.string({
|
|
35
|
-
description: "Permission mode",
|
|
36
|
-
options: ["default", "acceptEdits", "plan", "auto"],
|
|
37
|
-
}),
|
|
38
|
-
name: Flags.string({ description: "Custom session name" }),
|
|
39
|
-
resume: Flags.boolean({
|
|
40
|
-
description: "Resume the previous session for this project",
|
|
41
|
-
default: false,
|
|
42
|
-
}),
|
|
43
|
-
yolo: Flags.boolean({
|
|
44
|
-
description: "Skip all permission checks (alias for -- --dangerously-skip-permissions)",
|
|
45
|
-
default: false,
|
|
46
|
-
}),
|
|
47
|
-
telegram: Flags.boolean({
|
|
48
|
-
description: "Enable Telegram channel (enabled by default when configured)",
|
|
49
|
-
default: true,
|
|
50
|
-
allowNo: true,
|
|
51
|
-
}),
|
|
52
|
-
};
|
|
53
|
-
async run() {
|
|
54
|
-
const { args, flags, argv } = await this.parse(Spawn);
|
|
55
|
-
const extraClaudeArgs = argv;
|
|
56
|
-
const config = loadConfig();
|
|
57
|
-
if (flags.yolo) {
|
|
58
|
-
extraClaudeArgs.push("--dangerously-skip-permissions");
|
|
59
|
-
}
|
|
60
|
-
const projectDir = resolveProjectDir(args.project, config);
|
|
61
|
-
const projectName = args.project.startsWith("/") ? basename(args.project) : args.project;
|
|
62
|
-
if (!existsSync(projectDir)) {
|
|
63
|
-
this.error(`Directory not found: ${projectDir}`);
|
|
64
|
-
}
|
|
65
|
-
let workDir = projectDir;
|
|
66
|
-
let branchSuffix = "";
|
|
67
|
-
if (flags["new-worktree"]) {
|
|
68
|
-
log(`Creating worktree: ${flags["new-worktree"]}`);
|
|
69
|
-
workDir = createWorktree(projectDir, flags["new-worktree"]);
|
|
70
|
-
branchSuffix = `-${flags["new-worktree"].replace(/\//g, "-")}`;
|
|
71
|
-
log(`Worktree created at: ${workDir}`);
|
|
72
|
-
}
|
|
73
|
-
else if (flags.worktree) {
|
|
74
|
-
const wtPath = findWorktreePath(projectDir, flags.worktree);
|
|
75
|
-
if (!wtPath) {
|
|
76
|
-
this.error(`Worktree '${flags.worktree}' not found in ${projectDir}`);
|
|
77
|
-
}
|
|
78
|
-
workDir = wtPath;
|
|
79
|
-
branchSuffix = `-${flags.worktree.replace(/\//g, "-")}`;
|
|
80
|
-
}
|
|
81
|
-
const sessionName = sanitizeSessionName(flags.name ?? `hq-${projectName}${branchSuffix}`);
|
|
82
|
-
if (tmux.sessionExists(sessionName)) {
|
|
83
|
-
log(`Session '${sessionName}' is already running. Use 'hyper hq attach ${projectName}' to connect.`);
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
mkdirSync(LOG_DIR, { recursive: true });
|
|
87
|
-
const telegramEnv = flags.telegram ? getProjectTelegramEnv(projectName, config) : null;
|
|
88
|
-
const channels = [];
|
|
89
|
-
if (telegramEnv)
|
|
90
|
-
channels.push(TELEGRAM_CHANNEL_PLUGIN);
|
|
91
|
-
const logFile = resolve(LOG_DIR, `${sessionName}.log`);
|
|
92
|
-
const command = buildClaudeCommand({
|
|
93
|
-
name: sessionName,
|
|
94
|
-
resume: flags.resume,
|
|
95
|
-
permissionMode: flags["permission-mode"] ?? config.claude.permission_mode,
|
|
96
|
-
telegramBotToken: telegramEnv?.TELEGRAM_BOT_TOKEN,
|
|
97
|
-
channels,
|
|
98
|
-
extraArgs: extraClaudeArgs,
|
|
99
|
-
logFile,
|
|
100
|
-
});
|
|
101
|
-
log(`Spawning Claude session for: ${projectName}`);
|
|
102
|
-
log(`Working directory: ${workDir}`);
|
|
103
|
-
tmux.createSession({ name: sessionName, cwd: workDir, command });
|
|
104
|
-
if (tmux.waitAndVerify(sessionName) === "dead") {
|
|
105
|
-
this.error(`Session '${sessionName}' exited immediately after starting.
|
|
106
|
-
Check the log for details: ${logFile}
|
|
107
|
-
|
|
108
|
-
Common causes:
|
|
109
|
-
- Claude CLI is not authenticated (run: claude auth login)
|
|
110
|
-
- The claude command is not found (check your PATH)
|
|
111
|
-
- Telegram plugin not installed (run: claude plugin install telegram@claude-plugins-official)`);
|
|
112
|
-
}
|
|
113
|
-
tmux.disableRemainOnExit(sessionName);
|
|
114
|
-
log("");
|
|
115
|
-
log(`Session '${sessionName}' started`);
|
|
116
|
-
log("Connect via:");
|
|
117
|
-
log(` Web: claude.ai/code → find session '${sessionName}'`);
|
|
118
|
-
log(` Terminal: hyper hq attach ${projectName}`);
|
|
119
|
-
if (telegramEnv) {
|
|
120
|
-
log(` Telegram: Message the ${projectName} bot`);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
//# sourceMappingURL=spawn.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"spawn.js","sourceRoot":"","sources":["../../../src/commands/hq/spawn.ts"],"names":[],"mappings":"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"}
|