@hypercli/hq 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +24 -0
  3. package/dist/commands/hq/attach.d.ts +10 -0
  4. package/dist/commands/hq/attach.d.ts.map +1 -0
  5. package/dist/commands/hq/attach.js +29 -0
  6. package/dist/commands/hq/attach.js.map +1 -0
  7. package/dist/commands/hq/config.d.ts +12 -0
  8. package/dist/commands/hq/config.d.ts.map +1 -0
  9. package/dist/commands/hq/config.js +56 -0
  10. package/dist/commands/hq/config.js.map +1 -0
  11. package/dist/commands/hq/list.d.ts +12 -0
  12. package/dist/commands/hq/list.d.ts.map +1 -0
  13. package/dist/commands/hq/list.js +54 -0
  14. package/dist/commands/hq/list.js.map +1 -0
  15. package/dist/commands/hq/spawn.d.ts +17 -0
  16. package/dist/commands/hq/spawn.d.ts.map +1 -0
  17. package/dist/commands/hq/spawn.js +100 -0
  18. package/dist/commands/hq/spawn.js.map +1 -0
  19. package/dist/commands/hq/start.d.ts +14 -0
  20. package/dist/commands/hq/start.d.ts.map +1 -0
  21. package/dist/commands/hq/start.js +178 -0
  22. package/dist/commands/hq/start.js.map +1 -0
  23. package/dist/commands/hq/status.d.ts +11 -0
  24. package/dist/commands/hq/status.d.ts.map +1 -0
  25. package/dist/commands/hq/status.js +34 -0
  26. package/dist/commands/hq/status.js.map +1 -0
  27. package/dist/commands/hq/stop-all.d.ts +7 -0
  28. package/dist/commands/hq/stop-all.d.ts.map +1 -0
  29. package/dist/commands/hq/stop-all.js +20 -0
  30. package/dist/commands/hq/stop-all.js.map +1 -0
  31. package/dist/commands/hq/stop.d.ts +10 -0
  32. package/dist/commands/hq/stop.d.ts.map +1 -0
  33. package/dist/commands/hq/stop.js +28 -0
  34. package/dist/commands/hq/stop.js.map +1 -0
  35. package/dist/config/index.d.ts +6 -0
  36. package/dist/config/index.d.ts.map +1 -0
  37. package/dist/config/index.js +59 -0
  38. package/dist/config/index.js.map +1 -0
  39. package/dist/config/schema.d.ts +25 -0
  40. package/dist/config/schema.d.ts.map +1 -0
  41. package/dist/config/schema.js +17 -0
  42. package/dist/config/schema.js.map +1 -0
  43. package/dist/config/setup.d.ts +3 -0
  44. package/dist/config/setup.d.ts.map +1 -0
  45. package/dist/config/setup.js +147 -0
  46. package/dist/config/setup.js.map +1 -0
  47. package/dist/index.d.ts +3 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +4 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/lib/base-command.d.ts +17 -0
  52. package/dist/lib/base-command.d.ts.map +1 -0
  53. package/dist/lib/base-command.js +17 -0
  54. package/dist/lib/base-command.js.map +1 -0
  55. package/dist/services/claude.d.ts +11 -0
  56. package/dist/services/claude.d.ts.map +1 -0
  57. package/dist/services/claude.js +37 -0
  58. package/dist/services/claude.js.map +1 -0
  59. package/dist/services/projects.d.ts +20 -0
  60. package/dist/services/projects.d.ts.map +1 -0
  61. package/dist/services/projects.js +147 -0
  62. package/dist/services/projects.js.map +1 -0
  63. package/dist/services/telegram.d.ts +8 -0
  64. package/dist/services/telegram.d.ts.map +1 -0
  65. package/dist/services/telegram.js +26 -0
  66. package/dist/services/telegram.js.map +1 -0
  67. package/dist/services/tmux.d.ts +25 -0
  68. package/dist/services/tmux.d.ts.map +1 -0
  69. package/dist/services/tmux.js +87 -0
  70. package/dist/services/tmux.js.map +1 -0
  71. package/dist/utils/banner.d.ts +7 -0
  72. package/dist/utils/banner.d.ts.map +1 -0
  73. package/dist/utils/banner.js +80 -0
  74. package/dist/utils/banner.js.map +1 -0
  75. package/dist/utils/log.d.ts +2 -0
  76. package/dist/utils/log.d.ts.map +1 -0
  77. package/dist/utils/log.js +5 -0
  78. package/dist/utils/log.js.map +1 -0
  79. package/dist/utils/paths.d.ts +4 -0
  80. package/dist/utils/paths.d.ts.map +1 -0
  81. package/dist/utils/paths.js +10 -0
  82. package/dist/utils/paths.js.map +1 -0
  83. package/dist/utils/trust.d.ts +13 -0
  84. package/dist/utils/trust.d.ts.map +1 -0
  85. package/dist/utils/trust.js +29 -0
  86. package/dist/utils/trust.js.map +1 -0
  87. package/help/hq/attach.md +32 -0
  88. package/help/hq/config.md +50 -0
  89. package/help/hq/list.md +42 -0
  90. package/help/hq/spawn.md +47 -0
  91. package/help/hq/start.md +39 -0
  92. package/help/hq/status.md +38 -0
  93. package/help/hq/stop-all.md +20 -0
  94. package/help/hq/stop.md +31 -0
  95. package/help/hq.md +48 -0
  96. package/oclif.manifest.json +395 -0
  97. package/package.json +87 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Saulo Vallory
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,24 @@
1
+ # @hypercli/hq
2
+
3
+ Claude Code session management plugin for the `hyper` CLI. Manages persistent Claude sessions via tmux, accessible from claude.ai/code, mobile, and Telegram.
4
+
5
+ ## Install
6
+
7
+ Included automatically with `@hypercli/cli`. Can also be installed as a standalone oclif plugin.
8
+
9
+ ## Commands
10
+
11
+ - `hyper hq start` — Start the always-on HQ control center
12
+ - `hyper hq spawn <project>` — Spawn a Claude session for a project
13
+ - `hyper hq status` — Show running sessions
14
+ - `hyper hq list` — List available projects
15
+ - `hyper hq attach` — Attach to a tmux session
16
+ - `hyper hq stop` / `hyper hq stop-all` — Stop sessions
17
+
18
+ ## Documentation
19
+
20
+ Full documentation at [hyperdev.saulo.engineer](https://hyperdev.saulo.engineer).
21
+
22
+ ## License
23
+
24
+ MIT
@@ -0,0 +1,10 @@
1
+ import { BaseCommand } from "#lib/base-command";
2
+ export default class Attach extends BaseCommand<typeof Attach> {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ session: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
7
+ };
8
+ run(): Promise<void>;
9
+ }
10
+ //# sourceMappingURL=attach.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attach.d.ts","sourceRoot":"","sources":["../../../src/commands/hq/attach.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,MAAM,CAAC,OAAO,OAAO,MAAO,SAAQ,WAAW,CAAC,OAAO,MAAM,CAAC;IAC7D,OAAgB,WAAW,SAAkC;IAE7D,OAAgB,QAAQ,WAGtB;IAEF,OAAgB,IAAI;;MAKlB;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAc1B"}
@@ -0,0 +1,29 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { Args } from "@oclif/core";
3
+ import { BaseCommand } from "#lib/base-command";
4
+ import * as tmux from "#services/tmux";
5
+ export default class Attach extends BaseCommand {
6
+ static description = "Attach to an HQ tmux session";
7
+ static examples = [
8
+ "<%= config.bin %> hq attach",
9
+ "<%= config.bin %> hq attach my-project",
10
+ ];
11
+ static args = {
12
+ session: Args.string({
13
+ description: "Session name or project name (default: hyper-hq)",
14
+ required: false,
15
+ }),
16
+ };
17
+ async run() {
18
+ const { args } = await this.parse(Attach);
19
+ let target = args.session ?? "hyper-hq";
20
+ if (!target.startsWith("hq")) {
21
+ target = `hq-${target}`;
22
+ }
23
+ if (!tmux.sessionExists(target)) {
24
+ this.error(`Session '${target}' not found. Run 'hyper hq status' to see active sessions.`);
25
+ }
26
+ execFileSync("tmux", ["attach", "-t", target], { stdio: "inherit" });
27
+ }
28
+ }
29
+ //# sourceMappingURL=attach.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attach.js","sourceRoot":"","sources":["../../../src/commands/hq/attach.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACnC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,IAAI,MAAM,gBAAgB,CAAC;AAEvC,MAAM,CAAC,OAAO,OAAO,MAAO,SAAQ,WAA0B;IAC7D,MAAM,CAAU,WAAW,GAAG,8BAA8B,CAAC;IAE7D,MAAM,CAAU,QAAQ,GAAG;QAC1B,6BAA6B;QAC7B,wCAAwC;KACxC,CAAC;IAEF,MAAM,CAAU,IAAI,GAAG;QACtB,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC;YACpB,WAAW,EAAE,kDAAkD;YAC/D,QAAQ,EAAE,KAAK;SACf,CAAC;KACF,CAAC;IAEF,KAAK,CAAC,GAAG;QACR,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC1C,IAAI,MAAM,GAAG,IAAI,CAAC,OAAO,IAAI,UAAU,CAAC;QAExC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,MAAM,GAAG,MAAM,MAAM,EAAE,CAAC;QACzB,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;YACjC,IAAI,CAAC,KAAK,CAAC,YAAY,MAAM,4DAA4D,CAAC,CAAC;QAC5F,CAAC;QAED,YAAY,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IACtE,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { BaseCommand } from "#lib/base-command";
2
+ export default class Config extends BaseCommand<typeof Config> {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
7
+ path: import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
+ debug: import("@oclif/core/interfaces").BooleanFlag<boolean>;
9
+ };
10
+ run(): Promise<void>;
11
+ }
12
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/commands/hq/config.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,CAAC,OAAO,OAAO,MAAO,SAAQ,WAAW,CAAC,OAAO,MAAM,CAAC;IAC7D,OAAgB,WAAW,SAA2B;IAEtD,OAAgB,QAAQ,WAItB;IAEF,OAAgB,KAAK;;;;MAInB;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CA6C1B"}
@@ -0,0 +1,56 @@
1
+ import { Flags } from "@oclif/core";
2
+ import { CONFIG_PATH, configExists, loadConfig } from "#config/index";
3
+ import { BaseCommand } from "#lib/base-command";
4
+ export default class Config extends BaseCommand {
5
+ static description = "Show HQ configuration";
6
+ static examples = [
7
+ "<%= config.bin %> hq config",
8
+ "<%= config.bin %> hq config --json",
9
+ "<%= config.bin %> hq config --path",
10
+ ];
11
+ static flags = {
12
+ ...BaseCommand.baseFlags,
13
+ json: Flags.boolean({ description: "Output as JSON", default: false }),
14
+ path: Flags.boolean({ description: "Print config file path only", default: false }),
15
+ };
16
+ async run() {
17
+ const { flags } = await this.parse(Config);
18
+ if (flags.path) {
19
+ this.log(CONFIG_PATH);
20
+ return;
21
+ }
22
+ if (!configExists()) {
23
+ this.log(`No config file found at ${CONFIG_PATH}`);
24
+ this.log("");
25
+ this.log('Run "hyper hq start" to create one via the setup wizard.');
26
+ return;
27
+ }
28
+ const config = loadConfig();
29
+ if (flags.json) {
30
+ this.log(JSON.stringify(config, null, 2));
31
+ return;
32
+ }
33
+ const telegramStatus = config.telegram.hq_bot_token
34
+ ? "enabled (HQ bot configured)"
35
+ : "disabled";
36
+ const projectBotCount = Object.keys(config.telegram.project_bots).length;
37
+ const projectBotInfo = projectBotCount > 0 ? `${projectBotCount} project bot(s)` : "none";
38
+ const groupCount = Object.values(config.projects).filter((p) => p.type === "group").length;
39
+ const groupInfo = groupCount > 0 ? `${groupCount} group(s) configured` : "none";
40
+ this.log(`Config file: ${CONFIG_PATH}`);
41
+ this.log("");
42
+ this.log(` projects_root ${config.projects_root}`);
43
+ this.log(` hq.name ${config.hq.name}`);
44
+ this.log(` hq.dir ${config.hq.dir}`);
45
+ this.log(` hq.spawn_mode ${config.hq.spawn_mode}`);
46
+ this.log(` hq.capacity ${config.hq.capacity}`);
47
+ this.log(` claude.mode ${config.claude.permission_mode ?? "default"}`);
48
+ this.log(` telegram ${telegramStatus}`);
49
+ this.log(` project bots ${projectBotInfo}`);
50
+ this.log(` project groups ${groupInfo}`);
51
+ this.log("");
52
+ this.log(`Edit: ${CONFIG_PATH}`);
53
+ this.log("Docs: https://clint.saulo.engineer/getting-started/configuration");
54
+ }
55
+ }
56
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/commands/hq/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { BaseCommand } from "#lib/base-command";
2
+ export default class List extends BaseCommand<typeof List> {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ root: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
+ debug: import("@oclif/core/interfaces").BooleanFlag<boolean>;
9
+ };
10
+ run(): Promise<void>;
11
+ }
12
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/commands/hq/list.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,MAAM,CAAC,OAAO,OAAO,IAAK,SAAQ,WAAW,CAAC,OAAO,IAAI,CAAC;IACzD,OAAgB,WAAW,SAAiD;IAE5E,OAAgB,QAAQ,WAItB;IAEF,OAAgB,KAAK;;;;MAInB;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CA0C1B"}
@@ -0,0 +1,54 @@
1
+ import { Flags } from "@oclif/core";
2
+ import { loadConfig } from "#config/index";
3
+ import { BaseCommand } from "#lib/base-command";
4
+ import { listProjects } from "#services/projects";
5
+ export default class List extends BaseCommand {
6
+ static description = "List available projects and their worktrees";
7
+ static examples = [
8
+ "<%= config.bin %> hq list",
9
+ "<%= config.bin %> hq list --json",
10
+ "<%= config.bin %> hq list --root /path/to/projects",
11
+ ];
12
+ static flags = {
13
+ ...BaseCommand.baseFlags,
14
+ root: Flags.string({ description: "Override projects root directory" }),
15
+ json: Flags.boolean({ description: "Output as JSON", default: false }),
16
+ };
17
+ async run() {
18
+ const { flags } = await this.parse(List);
19
+ const config = loadConfig();
20
+ if (flags.root) {
21
+ config.projects_root = flags.root;
22
+ }
23
+ const projects = listProjects(config);
24
+ if (flags.json) {
25
+ this.log(JSON.stringify(projects, null, 2));
26
+ return;
27
+ }
28
+ this.log(`Projects (${config.projects_root})`);
29
+ this.log("─".repeat(50));
30
+ if (projects.length === 0) {
31
+ this.log(" No projects found");
32
+ return;
33
+ }
34
+ for (const project of projects) {
35
+ const tags = [];
36
+ if (project.isGit)
37
+ tags.push("git");
38
+ if (project.hasWorktrees)
39
+ tags.push(`${project.worktrees.length} worktrees`);
40
+ const tagStr = tags.length > 0 ? ` (${tags.join(", ")})` : "";
41
+ this.log(` ${project.name}${tagStr}`);
42
+ if (project.hasWorktrees) {
43
+ for (let i = 0; i < project.worktrees.length; i++) {
44
+ const wt = project.worktrees[i];
45
+ const isLast = i === project.worktrees.length - 1;
46
+ const prefix = isLast ? "└─" : "├─";
47
+ const mainTag = wt.isMain ? " *" : "";
48
+ this.log(` ${prefix} ${wt.branch}${mainTag} ${wt.path}`);
49
+ }
50
+ }
51
+ }
52
+ }
53
+ }
54
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/commands/hq/list.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
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 flags: {
9
+ worktree: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ "new-worktree": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
+ "permission-mode": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ name: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
13
+ debug: import("@oclif/core/interfaces").BooleanFlag<boolean>;
14
+ };
15
+ run(): Promise<void>;
16
+ }
17
+ //# sourceMappingURL=spawn.d.ts.map
@@ -0,0 +1 @@
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,WAKtB;IAEF,OAAgB,IAAI;;MAKlB;IAEF,OAAgB,KAAK;;;;;;MASnB;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CA8E1B"}
@@ -0,0 +1,100 @@
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 } from "#services/telegram";
9
+ import { sanitizeSessionName } from "#services/tmux";
10
+ import * as tmux 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
+ ];
21
+ static args = {
22
+ project: Args.string({
23
+ description: "Project name (under projects root) or absolute path",
24
+ required: true,
25
+ }),
26
+ };
27
+ static flags = {
28
+ ...BaseCommand.baseFlags,
29
+ worktree: Flags.string({ description: "Use an existing worktree (branch name)" }),
30
+ "new-worktree": Flags.string({ description: "Create a new worktree via wt switch -c" }),
31
+ "permission-mode": Flags.string({
32
+ description: "Permission mode",
33
+ options: ["default", "acceptEdits", "plan", "auto"],
34
+ }),
35
+ name: Flags.string({ description: "Custom session name" }),
36
+ };
37
+ async run() {
38
+ const { args, flags } = await this.parse(Spawn);
39
+ const config = loadConfig();
40
+ const projectDir = resolveProjectDir(args.project, config);
41
+ const projectName = args.project.startsWith("/") ? basename(args.project) : args.project;
42
+ if (!existsSync(projectDir)) {
43
+ this.error(`Directory not found: ${projectDir}`);
44
+ }
45
+ let workDir = projectDir;
46
+ let branchSuffix = "";
47
+ if (flags["new-worktree"]) {
48
+ log(`Creating worktree: ${flags["new-worktree"]}`);
49
+ workDir = createWorktree(projectDir, flags["new-worktree"]);
50
+ branchSuffix = `-${flags["new-worktree"].replace(/\//g, "-")}`;
51
+ log(`Worktree created at: ${workDir}`);
52
+ }
53
+ else if (flags.worktree) {
54
+ const wtPath = findWorktreePath(projectDir, flags.worktree);
55
+ if (!wtPath) {
56
+ this.error(`Worktree '${flags.worktree}' not found in ${projectDir}`);
57
+ }
58
+ workDir = wtPath;
59
+ branchSuffix = `-${flags.worktree.replace(/\//g, "-")}`;
60
+ }
61
+ const sessionName = sanitizeSessionName(flags.name ?? `hq-${projectName}${branchSuffix}`);
62
+ if (tmux.sessionExists(sessionName)) {
63
+ log(`Session '${sessionName}' is already running. Use 'hyper hq attach ${projectName}' to connect.`);
64
+ return;
65
+ }
66
+ mkdirSync(LOG_DIR, { recursive: true });
67
+ const telegramEnv = getProjectTelegramEnv(projectName, config);
68
+ const logFile = resolve(LOG_DIR, `${sessionName}.log`);
69
+ const command = buildClaudeCommand({
70
+ name: sessionName,
71
+ spawnMode: "same-dir",
72
+ permissionMode: flags["permission-mode"] ?? config.claude.permission_mode,
73
+ telegramBotToken: telegramEnv?.TELEGRAM_BOT_TOKEN,
74
+ telegramStateDir: telegramEnv?.TELEGRAM_STATE_DIR,
75
+ logFile,
76
+ });
77
+ log(`Spawning Claude session for: ${projectName}`);
78
+ log(`Working directory: ${workDir}`);
79
+ tmux.createSession({ name: sessionName, cwd: workDir, command });
80
+ if (tmux.waitAndVerify(sessionName) === "dead") {
81
+ this.error(`Session '${sessionName}' exited immediately after starting.
82
+ Check the log for details: ${logFile}
83
+
84
+ Common causes:
85
+ - Remote Control is not enabled on your account
86
+ - Claude CLI is not authenticated (run: claude auth login)
87
+ - The claude command is not found (check your PATH)`);
88
+ }
89
+ tmux.disableRemainOnExit(sessionName);
90
+ log("");
91
+ log(`Session '${sessionName}' started`);
92
+ log("Connect via:");
93
+ log(` Web: claude.ai/code → find session '${sessionName}'`);
94
+ log(` Terminal: hyper hq attach ${projectName}`);
95
+ if (telegramEnv) {
96
+ log(` Telegram: Message the ${projectName} bot`);
97
+ }
98
+ }
99
+ }
100
+ //# sourceMappingURL=spawn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn.js","sourceRoot":"","sources":["../../../src/commands/hq/spawn.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { BaseCommand } from "#lib/base-command";
2
+ export default class Start extends BaseCommand<typeof Start> {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ name: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
7
+ "spawn-mode": import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
8
+ "permission-mode": import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
9
+ capacity: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
10
+ debug: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
+ };
12
+ run(): Promise<void>;
13
+ }
14
+ //# sourceMappingURL=start.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../../src/commands/hq/start.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAchD,MAAM,CAAC,OAAO,OAAO,KAAM,SAAQ,WAAW,CAAC,OAAO,KAAK,CAAC;IAC3D,OAAgB,WAAW,SAAiE;IAE5F,OAAgB,QAAQ,WAItB;IAEF,OAAgB,KAAK;;;;;;MAcnB;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAkG1B"}
@@ -0,0 +1,178 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
+ import { resolve } from "node:path";
4
+ import * as p from "@clack/prompts";
5
+ import { Flags } from "@oclif/core";
6
+ import { runSetupIfNeeded } from "#config/setup";
7
+ import { BaseCommand } from "#lib/base-command";
8
+ import { buildClaudeCommand } from "#services/claude";
9
+ import { getHqTelegramEnv } from "#services/telegram";
10
+ import * as tmux from "#services/tmux";
11
+ import { renderBanner } from "#utils/banner";
12
+ import { log } from "#utils/log";
13
+ import { LOG_DIR } from "#utils/paths";
14
+ import { isWorkspaceTrusted, trustWorkspace } from "#utils/trust";
15
+ function isHyperOnPath() {
16
+ const result = spawnSync("which", ["hyper"], { encoding: "utf-8" });
17
+ return result.status === 0;
18
+ }
19
+ export default class Start extends BaseCommand {
20
+ static description = "Start the HQ session — always-on Claude Code command center";
21
+ static examples = [
22
+ "<%= config.bin %> hq start",
23
+ "<%= config.bin %> hq start --spawn-mode worktree",
24
+ "<%= config.bin %> hq start --capacity 16",
25
+ ];
26
+ static flags = {
27
+ ...BaseCommand.baseFlags,
28
+ name: Flags.string({ description: "Custom session name", default: undefined }),
29
+ "spawn-mode": Flags.string({
30
+ description: "How new sessions are created",
31
+ options: ["same-dir", "worktree", "session"],
32
+ default: undefined,
33
+ }),
34
+ "permission-mode": Flags.string({
35
+ description: "Permission mode for sessions",
36
+ options: ["default", "acceptEdits", "plan", "auto"],
37
+ default: undefined,
38
+ }),
39
+ capacity: Flags.integer({ description: "Max concurrent sessions", default: undefined }),
40
+ };
41
+ async run() {
42
+ const { flags } = await this.parse(Start);
43
+ const config = await runSetupIfNeeded();
44
+ const sessionName = flags.name ?? config.hq.name;
45
+ const spawnMode = flags["spawn-mode"] ?? config.hq.spawn_mode;
46
+ const capacity = flags.capacity ?? config.hq.capacity;
47
+ const permissionMode = flags["permission-mode"] ?? config.claude.permission_mode;
48
+ // Suggest global install if not on PATH
49
+ if (!isHyperOnPath()) {
50
+ p.log.warning("Hyper CLI is not installed globally. The HQ session won't be able to run hyper commands.\n" +
51
+ " Install globally:\n\n" +
52
+ " npm install -g @hypercli/cli\n" +
53
+ " # or: bun install -g @hypercli/cli\n");
54
+ }
55
+ // Ensure HQ directory exists
56
+ const hqDir = config.hq.dir;
57
+ if (!existsSync(hqDir)) {
58
+ mkdirSync(hqDir, { recursive: true });
59
+ log(`Created HQ directory: ${hqDir}`);
60
+ }
61
+ // Generate CLAUDE.md for the HQ session if not present
62
+ const claudeMdPath = resolve(hqDir, "CLAUDE.md");
63
+ if (!existsSync(claudeMdPath)) {
64
+ writeFileSync(claudeMdPath, generateHqClaudeMd(config.projects_root), "utf-8");
65
+ log("Generated CLAUDE.md for HQ session.");
66
+ }
67
+ // Ensure workspace trust for both HQ dir and projects root
68
+ for (const dir of [hqDir, config.projects_root]) {
69
+ if (!isWorkspaceTrusted(dir)) {
70
+ trustWorkspace(dir);
71
+ log(`Trusted ${dir} for Claude Code.`);
72
+ }
73
+ }
74
+ if (tmux.sessionExists(sessionName)) {
75
+ log(`Session '${sessionName}' is already running. Use 'hyper hq attach' to connect.`);
76
+ return;
77
+ }
78
+ mkdirSync(LOG_DIR, { recursive: true });
79
+ const telegramEnv = config.telegram.hq_bot_token ? getHqTelegramEnv(config) : null;
80
+ const logFile = resolve(LOG_DIR, `${sessionName}.log`);
81
+ const command = buildClaudeCommand({
82
+ name: sessionName,
83
+ spawnMode,
84
+ capacity,
85
+ permissionMode,
86
+ telegramBotToken: telegramEnv?.TELEGRAM_BOT_TOKEN,
87
+ telegramStateDir: telegramEnv?.TELEGRAM_STATE_DIR,
88
+ logFile,
89
+ });
90
+ const cwd = hqDir;
91
+ log(`Starting HQ session: ${sessionName}`);
92
+ tmux.createSession({ name: sessionName, cwd, command });
93
+ // Verify the session actually survived startup
94
+ if (tmux.waitAndVerify(sessionName) === "dead") {
95
+ let lastError = "";
96
+ try {
97
+ const logContent = readFileSync(logFile, "utf-8");
98
+ const errorLines = logContent.split("\n").filter((l) => l.startsWith("Error:"));
99
+ if (errorLines.length > 0) {
100
+ lastError = `\nLast error from log:\n ${errorLines[errorLines.length - 1]}\n`;
101
+ }
102
+ }
103
+ catch { }
104
+ this.error(`Session '${sessionName}' exited immediately after starting.
105
+ ${lastError}
106
+ Full log: ${logFile}
107
+
108
+ Common causes:
109
+ - Remote Control is not enabled on your account
110
+ - Claude CLI is not authenticated (run: claude auth login)
111
+ - Workspace not trusted (run: cd <dir> && claude)
112
+ - The claude command is not found (check your PATH)`);
113
+ }
114
+ // Session survived — disable remain-on-exit so panes clean up normally
115
+ tmux.disableRemainOnExit(sessionName);
116
+ // Show welcome banner
117
+ this.log(renderBanner({ config, sessionName, logFile }));
118
+ }
119
+ }
120
+ function generateHqClaudeMd(projectsRoot) {
121
+ return `# Hyper HQ — Claude Code Command Center
122
+
123
+ You are **Hyper HQ**, an always-running Claude Code instance that serves as a command center.
124
+ Calm, decisive, and always in control.
125
+
126
+ ## Your Role
127
+
128
+ You are a persistent Claude Code session running in remote-control server mode.
129
+ Users connect to you from claude.ai/code, mobile apps, or via Telegram.
130
+
131
+ ## On Startup
132
+
133
+ When this session first starts, immediately:
134
+ 1. If Telegram is available, use the \`reply\` tool to send: "Hyper HQ is online. Ready for orders."
135
+ 2. Run \`hyper hq list --json\` to get the current project inventory.
136
+
137
+ ## Capabilities
138
+
139
+ 1. **Spawn new Claude sessions** for any project using the \`hyper hq\` CLI
140
+ 2. **Receive and act on messages** via Telegram (if configured)
141
+ 3. **Manage running sessions** — start, stop, check status
142
+ 4. **Coordinate work** across multiple projects
143
+
144
+ ## Key Commands
145
+
146
+ \`\`\`bash
147
+ hyper hq spawn <project> # Spawn session for a project
148
+ hyper hq spawn <project> --worktree <branch> # Spawn on existing worktree
149
+ hyper hq spawn <project> --new-worktree <branch> # Create worktree + spawn
150
+ hyper hq status # Check all running sessions
151
+ hyper hq stop <project> # Stop a session
152
+ hyper hq stop-all # Stop everything
153
+ hyper hq list # List all projects and worktrees
154
+ hyper hq list --json # JSON output for parsing
155
+ hyper hq config # Show current configuration
156
+ \`\`\`
157
+
158
+ ## Handling Requests
159
+
160
+ When a user asks to open/start/spawn a session:
161
+
162
+ 1. Parse the request for: **project name** and optionally **worktree** (existing or new)
163
+ 2. Run \`hyper hq list --json\` to verify the project exists
164
+ 3. Run the appropriate spawn command
165
+ 4. Reply with confirmation, session name, and remind them to check **claude.ai/code**
166
+
167
+ ## Important Notes
168
+
169
+ - Projects root: ${projectsRoot}
170
+ - Logs: ~/.config/hyper/logs/
171
+ - The \`wt\` (worktrunk) command manages worktrees
172
+ - Config: ~/.config/hyper/hq.toml
173
+
174
+ ## Package Management
175
+ - Use bun, never npm
176
+ `;
177
+ }
178
+ //# sourceMappingURL=start.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.js","sourceRoot":"","sources":["../../../src/commands/hq/start.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { BaseCommand } from "#lib/base-command";
2
+ export default class Status extends BaseCommand<typeof Status> {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
7
+ debug: import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
+ };
9
+ run(): Promise<void>;
10
+ }
11
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/commands/hq/status.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,MAAM,CAAC,OAAO,OAAO,MAAO,SAAQ,WAAW,CAAC,OAAO,MAAM,CAAC;IAC7D,OAAgB,WAAW,SAA8B;IAEzD,OAAgB,QAAQ,WAAyE;IAEjG,OAAgB,KAAK;;;MAGnB;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CA0B1B"}