jfl 0.1.0 → 0.2.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.
Files changed (262) hide show
  1. package/README.md +443 -145
  2. package/clawdbot-plugin/clawdbot.plugin.json +20 -0
  3. package/clawdbot-plugin/index.js +555 -0
  4. package/clawdbot-plugin/index.ts +582 -0
  5. package/clawdbot-skill/SKILL.md +33 -336
  6. package/clawdbot-skill/index.ts +491 -321
  7. package/clawdbot-skill/skill.json +4 -13
  8. package/dist/commands/clawdbot.d.ts +11 -0
  9. package/dist/commands/clawdbot.d.ts.map +1 -0
  10. package/dist/commands/clawdbot.js +215 -0
  11. package/dist/commands/clawdbot.js.map +1 -0
  12. package/dist/commands/context-hub.d.ts +5 -0
  13. package/dist/commands/context-hub.d.ts.map +1 -1
  14. package/dist/commands/context-hub.js +394 -28
  15. package/dist/commands/context-hub.js.map +1 -1
  16. package/dist/commands/gtm-process-update.d.ts +10 -0
  17. package/dist/commands/gtm-process-update.d.ts.map +1 -0
  18. package/dist/commands/gtm-process-update.js +101 -0
  19. package/dist/commands/gtm-process-update.js.map +1 -0
  20. package/dist/commands/init.d.ts.map +1 -1
  21. package/dist/commands/init.js +278 -4
  22. package/dist/commands/init.js.map +1 -1
  23. package/dist/commands/login.d.ts.map +1 -1
  24. package/dist/commands/login.js +32 -33
  25. package/dist/commands/login.js.map +1 -1
  26. package/dist/commands/memory.d.ts +38 -0
  27. package/dist/commands/memory.d.ts.map +1 -0
  28. package/dist/commands/memory.js +229 -0
  29. package/dist/commands/memory.js.map +1 -0
  30. package/dist/commands/migrate-services.d.ts +8 -0
  31. package/dist/commands/migrate-services.d.ts.map +1 -0
  32. package/dist/commands/migrate-services.js +182 -0
  33. package/dist/commands/migrate-services.js.map +1 -0
  34. package/dist/commands/onboard.d.ts +24 -0
  35. package/dist/commands/onboard.d.ts.map +1 -0
  36. package/dist/commands/onboard.js +663 -0
  37. package/dist/commands/onboard.js.map +1 -0
  38. package/dist/commands/openclaw.d.ts +56 -0
  39. package/dist/commands/openclaw.d.ts.map +1 -0
  40. package/dist/commands/openclaw.js +700 -0
  41. package/dist/commands/openclaw.js.map +1 -0
  42. package/dist/commands/orchestrate.d.ts +14 -0
  43. package/dist/commands/orchestrate.d.ts.map +1 -0
  44. package/dist/commands/orchestrate.js +270 -0
  45. package/dist/commands/orchestrate.js.map +1 -0
  46. package/dist/commands/profile.d.ts +46 -0
  47. package/dist/commands/profile.d.ts.map +1 -0
  48. package/dist/commands/profile.js +498 -0
  49. package/dist/commands/profile.js.map +1 -0
  50. package/dist/commands/repair.d.ts.map +1 -1
  51. package/dist/commands/repair.js +37 -0
  52. package/dist/commands/repair.js.map +1 -1
  53. package/dist/commands/service-agent.d.ts +16 -0
  54. package/dist/commands/service-agent.d.ts.map +1 -0
  55. package/dist/commands/service-agent.js +375 -0
  56. package/dist/commands/service-agent.js.map +1 -0
  57. package/dist/commands/service-manager.d.ts +12 -0
  58. package/dist/commands/service-manager.d.ts.map +1 -0
  59. package/dist/commands/service-manager.js +967 -0
  60. package/dist/commands/service-manager.js.map +1 -0
  61. package/dist/commands/service-validate.d.ts +12 -0
  62. package/dist/commands/service-validate.d.ts.map +1 -0
  63. package/dist/commands/service-validate.js +611 -0
  64. package/dist/commands/service-validate.js.map +1 -0
  65. package/dist/commands/services-create.d.ts +15 -0
  66. package/dist/commands/services-create.d.ts.map +1 -0
  67. package/dist/commands/services-create.js +1452 -0
  68. package/dist/commands/services-create.js.map +1 -0
  69. package/dist/commands/services-scan.d.ts +13 -0
  70. package/dist/commands/services-scan.d.ts.map +1 -0
  71. package/dist/commands/services-scan.js +251 -0
  72. package/dist/commands/services-scan.js.map +1 -0
  73. package/dist/commands/services-sync-agents.d.ts +23 -0
  74. package/dist/commands/services-sync-agents.d.ts.map +1 -0
  75. package/dist/commands/services-sync-agents.js +207 -0
  76. package/dist/commands/services-sync-agents.js.map +1 -0
  77. package/dist/commands/services.d.ts +19 -0
  78. package/dist/commands/services.d.ts.map +1 -0
  79. package/dist/commands/services.js +742 -0
  80. package/dist/commands/services.js.map +1 -0
  81. package/dist/commands/session.d.ts +5 -1
  82. package/dist/commands/session.d.ts.map +1 -1
  83. package/dist/commands/session.js +68 -586
  84. package/dist/commands/session.js.map +1 -1
  85. package/dist/commands/status.d.ts.map +1 -1
  86. package/dist/commands/status.js +17 -0
  87. package/dist/commands/status.js.map +1 -1
  88. package/dist/commands/update.d.ts.map +1 -1
  89. package/dist/commands/update.js +75 -21
  90. package/dist/commands/update.js.map +1 -1
  91. package/dist/commands/validate-settings.d.ts +37 -0
  92. package/dist/commands/validate-settings.d.ts.map +1 -0
  93. package/dist/commands/validate-settings.js +197 -0
  94. package/dist/commands/validate-settings.js.map +1 -0
  95. package/dist/commands/voice.d.ts +0 -1
  96. package/dist/commands/voice.d.ts.map +1 -1
  97. package/dist/commands/voice.js +16 -15
  98. package/dist/commands/voice.js.map +1 -1
  99. package/dist/index.js +395 -141
  100. package/dist/index.js.map +1 -1
  101. package/dist/lib/agent-generator.d.ts +26 -0
  102. package/dist/lib/agent-generator.d.ts.map +1 -0
  103. package/dist/lib/agent-generator.js +331 -0
  104. package/dist/lib/agent-generator.js.map +1 -0
  105. package/dist/lib/memory-db.d.ts +102 -0
  106. package/dist/lib/memory-db.d.ts.map +1 -0
  107. package/dist/lib/memory-db.js +313 -0
  108. package/dist/lib/memory-db.js.map +1 -0
  109. package/dist/lib/memory-indexer.d.ts +47 -0
  110. package/dist/lib/memory-indexer.d.ts.map +1 -0
  111. package/dist/lib/memory-indexer.js +215 -0
  112. package/dist/lib/memory-indexer.js.map +1 -0
  113. package/dist/lib/memory-search.d.ts +41 -0
  114. package/dist/lib/memory-search.d.ts.map +1 -0
  115. package/dist/lib/memory-search.js +246 -0
  116. package/dist/lib/memory-search.js.map +1 -0
  117. package/dist/lib/openclaw-registry.d.ts +48 -0
  118. package/dist/lib/openclaw-registry.d.ts.map +1 -0
  119. package/dist/lib/openclaw-registry.js +181 -0
  120. package/dist/lib/openclaw-registry.js.map +1 -0
  121. package/dist/lib/openclaw-sdk.d.ts +107 -0
  122. package/dist/lib/openclaw-sdk.d.ts.map +1 -0
  123. package/dist/lib/openclaw-sdk.js +208 -0
  124. package/dist/lib/openclaw-sdk.js.map +1 -0
  125. package/dist/lib/peer-agent-generator.d.ts +44 -0
  126. package/dist/lib/peer-agent-generator.d.ts.map +1 -0
  127. package/dist/lib/peer-agent-generator.js +286 -0
  128. package/dist/lib/peer-agent-generator.js.map +1 -0
  129. package/dist/lib/service-dependencies.d.ts +44 -0
  130. package/dist/lib/service-dependencies.d.ts.map +1 -0
  131. package/dist/lib/service-dependencies.js +314 -0
  132. package/dist/lib/service-dependencies.js.map +1 -0
  133. package/dist/lib/service-detector.d.ts +61 -0
  134. package/dist/lib/service-detector.d.ts.map +1 -0
  135. package/dist/lib/service-detector.js +521 -0
  136. package/dist/lib/service-detector.js.map +1 -0
  137. package/dist/lib/service-gtm.d.ts +157 -0
  138. package/dist/lib/service-gtm.d.ts.map +1 -0
  139. package/dist/lib/service-gtm.js +786 -0
  140. package/dist/lib/service-gtm.js.map +1 -0
  141. package/dist/lib/service-mcp-base.d.ts +103 -0
  142. package/dist/lib/service-mcp-base.d.ts.map +1 -0
  143. package/dist/lib/service-mcp-base.js +263 -0
  144. package/dist/lib/service-mcp-base.js.map +1 -0
  145. package/dist/lib/service-utils.d.ts +103 -0
  146. package/dist/lib/service-utils.d.ts.map +1 -0
  147. package/dist/lib/service-utils.js +368 -0
  148. package/dist/lib/service-utils.js.map +1 -0
  149. package/dist/lib/skill-generator.d.ts +21 -0
  150. package/dist/lib/skill-generator.d.ts.map +1 -0
  151. package/dist/lib/skill-generator.js +253 -0
  152. package/dist/lib/skill-generator.js.map +1 -0
  153. package/dist/lib/stratus-client.d.ts +100 -0
  154. package/dist/lib/stratus-client.d.ts.map +1 -0
  155. package/dist/lib/stratus-client.js +255 -0
  156. package/dist/lib/stratus-client.js.map +1 -0
  157. package/dist/mcp/context-hub-mcp.js +135 -53
  158. package/dist/mcp/context-hub-mcp.js.map +1 -1
  159. package/dist/mcp/service-mcp-server.d.ts +12 -0
  160. package/dist/mcp/service-mcp-server.d.ts.map +1 -0
  161. package/dist/mcp/service-mcp-server.js +434 -0
  162. package/dist/mcp/service-mcp-server.js.map +1 -0
  163. package/dist/mcp/service-peer-mcp.d.ts +36 -0
  164. package/dist/mcp/service-peer-mcp.d.ts.map +1 -0
  165. package/dist/mcp/service-peer-mcp.js +220 -0
  166. package/dist/mcp/service-peer-mcp.js.map +1 -0
  167. package/dist/mcp/service-registry-mcp.d.ts +13 -0
  168. package/dist/mcp/service-registry-mcp.d.ts.map +1 -0
  169. package/dist/mcp/service-registry-mcp.js +330 -0
  170. package/dist/mcp/service-registry-mcp.js.map +1 -0
  171. package/dist/ui/banner.js +1 -1
  172. package/dist/ui/banner.js.map +1 -1
  173. package/dist/ui/context-hub-logs.d.ts +10 -0
  174. package/dist/ui/context-hub-logs.d.ts.map +1 -0
  175. package/dist/ui/context-hub-logs.js +175 -0
  176. package/dist/ui/context-hub-logs.js.map +1 -0
  177. package/dist/ui/service-dashboard.d.ts +11 -0
  178. package/dist/ui/service-dashboard.d.ts.map +1 -0
  179. package/dist/ui/service-dashboard.js +357 -0
  180. package/dist/ui/service-dashboard.js.map +1 -0
  181. package/dist/ui/services-manager.d.ts +11 -0
  182. package/dist/ui/services-manager.d.ts.map +1 -0
  183. package/dist/ui/services-manager.js +507 -0
  184. package/dist/ui/services-manager.js.map +1 -0
  185. package/dist/utils/auth-guard.d.ts.map +1 -1
  186. package/dist/utils/auth-guard.js +8 -9
  187. package/dist/utils/auth-guard.js.map +1 -1
  188. package/dist/utils/claude-md-generator.d.ts +10 -0
  189. package/dist/utils/claude-md-generator.d.ts.map +1 -0
  190. package/dist/utils/claude-md-generator.js +215 -0
  191. package/dist/utils/claude-md-generator.js.map +1 -0
  192. package/dist/utils/ensure-context-hub.d.ts +20 -0
  193. package/dist/utils/ensure-context-hub.d.ts.map +1 -0
  194. package/dist/utils/ensure-context-hub.js +65 -0
  195. package/dist/utils/ensure-context-hub.js.map +1 -0
  196. package/dist/utils/ensure-project.d.ts.map +1 -1
  197. package/dist/utils/ensure-project.js +3 -4
  198. package/dist/utils/ensure-project.js.map +1 -1
  199. package/dist/utils/jfl-config.d.ts +19 -0
  200. package/dist/utils/jfl-config.d.ts.map +1 -0
  201. package/dist/utils/jfl-config.js +112 -0
  202. package/dist/utils/jfl-config.js.map +1 -0
  203. package/dist/utils/jfl-migration.d.ts +29 -0
  204. package/dist/utils/jfl-migration.d.ts.map +1 -0
  205. package/dist/utils/jfl-migration.js +142 -0
  206. package/dist/utils/jfl-migration.js.map +1 -0
  207. package/dist/utils/jfl-paths.d.ts +55 -0
  208. package/dist/utils/jfl-paths.d.ts.map +1 -0
  209. package/dist/utils/jfl-paths.js +120 -0
  210. package/dist/utils/jfl-paths.js.map +1 -0
  211. package/dist/utils/settings-validator.d.ts +73 -0
  212. package/dist/utils/settings-validator.d.ts.map +1 -0
  213. package/dist/utils/settings-validator.js +222 -0
  214. package/dist/utils/settings-validator.js.map +1 -0
  215. package/package.json +19 -3
  216. package/scripts/commit-gtm.sh +56 -0
  217. package/scripts/commit-product.sh +68 -0
  218. package/scripts/context-query.sh +45 -0
  219. package/scripts/session/auto-commit.sh +297 -0
  220. package/scripts/session/jfl-doctor.sh +707 -0
  221. package/scripts/session/session-cleanup.sh +268 -0
  222. package/scripts/session/session-end.sh +198 -0
  223. package/scripts/session/session-init.sh +350 -0
  224. package/scripts/session/session-init.sh.backup +292 -0
  225. package/scripts/session/session-sync.sh +167 -0
  226. package/scripts/session/test-context-preservation.sh +160 -0
  227. package/scripts/session/test-critical-infrastructure.sh +293 -0
  228. package/scripts/session/test-experience-level.sh +336 -0
  229. package/scripts/session/test-session-cleanup.sh +268 -0
  230. package/scripts/session/test-session-sync.sh +320 -0
  231. package/scripts/voice-start.sh +36 -8
  232. package/scripts/where-am-i.sh +78 -0
  233. package/template/.claude/service-settings.json +32 -0
  234. package/template/.claude/settings.json +14 -1
  235. package/template/.claude/skills/end/SKILL.md +1780 -0
  236. package/template/.jfl/config.json +2 -1
  237. package/template/CLAUDE.md +1039 -134
  238. package/template/CLAUDE.md.bak +1187 -0
  239. package/template/scripts/commit-gtm.sh +56 -0
  240. package/template/scripts/commit-product.sh +68 -0
  241. package/template/scripts/migrate-to-branch-sessions.sh +201 -0
  242. package/template/scripts/session/auto-commit.sh +58 -6
  243. package/template/scripts/session/jfl-doctor.sh +137 -17
  244. package/template/scripts/session/session-cleanup.sh +268 -0
  245. package/template/scripts/session/session-end.sh +4 -0
  246. package/template/scripts/session/session-init.sh +253 -66
  247. package/template/scripts/session/test-critical-infrastructure.sh +293 -0
  248. package/template/scripts/session/test-experience-level.sh +336 -0
  249. package/template/scripts/session/test-session-cleanup.sh +268 -0
  250. package/template/scripts/session/test-session-sync.sh +320 -0
  251. package/template/scripts/where-am-i.sh +78 -0
  252. package/template/templates/service-agent/.claude/settings.json +32 -0
  253. package/template/templates/service-agent/CLAUDE.md +334 -0
  254. package/template/templates/service-agent/knowledge/ARCHITECTURE.md +115 -0
  255. package/template/templates/service-agent/knowledge/DEPLOYMENT.md +199 -0
  256. package/template/templates/service-agent/knowledge/RUNBOOK.md +412 -0
  257. package/template/templates/service-agent/knowledge/SERVICE_SPEC.md +77 -0
  258. package/dist/commands/session-mgmt.d.ts +0 -33
  259. package/dist/commands/session-mgmt.d.ts.map +0 -1
  260. package/dist/commands/session-mgmt.js +0 -404
  261. package/dist/commands/session-mgmt.js.map +0 -1
  262. package/template/scripts/session/auto-merge.sh +0 -325
package/dist/index.js CHANGED
@@ -7,13 +7,13 @@
7
7
  */
8
8
  import { Command } from "commander";
9
9
  import chalk from "chalk";
10
- import { spawn, execSync } from "child_process";
11
- import { existsSync, symlinkSync, mkdirSync, unlinkSync } from "fs";
12
- import { homedir } from "os";
10
+ import { spawn } from "child_process";
13
11
  import { join } from "path";
12
+ import * as path from "path";
14
13
  import { fileURLToPath } from "url";
15
14
  import { initCommand } from "./commands/init.js";
16
15
  import { repairCommand } from "./commands/repair.js";
16
+ import { validateSettingsCommand } from "./commands/validate-settings.js";
17
17
  import { loginCommand, logout } from "./commands/login.js";
18
18
  import { statusCommand } from "./commands/status.js";
19
19
  import { deployCommand } from "./commands/deploy.js";
@@ -25,15 +25,23 @@ import { updateCommand } from "./commands/update.js";
25
25
  import { contextHubCommand } from "./commands/context-hub.js";
26
26
  import { voiceCommand } from "./commands/voice.js";
27
27
  import { synopsisCommand } from "./commands/synopsis.js";
28
+ import { onboardCommand } from "./commands/onboard.js";
29
+ import { profileCommand } from "./commands/profile.js";
30
+ import { migrateServices } from "./commands/migrate-services.js";
31
+ import { memoryInitCommand, memoryStatusCommand, memorySearchCommand, memoryIndexCommand } from "./commands/memory.js";
28
32
  import { listSkillsCommand, installSkillCommand, removeSkillCommand, updateSkillsCommand, searchSkillsCommand, } from "./commands/skills.js";
29
33
  import { ralphCommand, showRalphHelp } from "./commands/ralph.js";
30
- import { sessionCreate, sessionExec, sessionList, sessionDestroy, sessionInfo } from "./commands/session-mgmt.js";
34
+ import { clawdbotSetupCommand, clawdbotStatusCommand } from "./commands/clawdbot.js";
31
35
  import { showDayPassStatus, hasWallet, getWalletAddress, } from "./utils/auth-guard.js";
36
+ import { checkAndMigrate } from "./utils/jfl-migration.js";
37
+ import { JFL_PATHS } from "./utils/jfl-paths.js";
38
+ // Auto-migrate from ~/.jfl/ to XDG directories if needed
39
+ await checkAndMigrate({ silent: true });
32
40
  const program = new Command();
33
41
  program
34
42
  .name("jfl")
35
- .description("Just Fucking Launch - AI-powered GTM and development")
36
- .version("0.1.0")
43
+ .description("Just Fucking Launch - AI gateway for GTM")
44
+ .version("0.1.1")
37
45
  .option("--no-update", "Skip automatic update check")
38
46
  .action(async (options) => {
39
47
  // Always update on session start (unless --no-update flag)
@@ -41,7 +49,7 @@ program
41
49
  await updateCommand({ autoUpdate: true });
42
50
  console.log(); // Add spacing before session starts
43
51
  }
44
- await sessionCommand();
52
+ await sessionCommand({});
45
53
  });
46
54
  // ============================================================================
47
55
  // FREE TIER COMMANDS (work offline/standalone)
@@ -55,6 +63,12 @@ program
55
63
  .command("repair")
56
64
  .description("Repair a JFL project missing .jfl directory")
57
65
  .action(repairCommand);
66
+ program
67
+ .command("validate-settings")
68
+ .description("Validate and repair .claude/settings.json")
69
+ .option("--fix", "Attempt to auto-repair common issues")
70
+ .option("--json", "Output in JSON format")
71
+ .action(validateSettingsCommand);
58
72
  program
59
73
  .command("hud")
60
74
  .description("Show campaign dashboard")
@@ -69,8 +83,12 @@ program
69
83
  .description("Manage Context Hub daemon (unified context for AI agents)")
70
84
  .argument("[action]", "start, stop, restart, status, ensure, query, serve")
71
85
  .option("-p, --port <port>", "Port to run on (default: 4242)", "4242")
86
+ .option("-g, --global", "Run in global mode (serve all GTM projects)")
72
87
  .action(async (action, options) => {
73
- await contextHubCommand(action, { port: parseInt(options.port, 10) });
88
+ await contextHubCommand(action, {
89
+ port: parseInt(options.port, 10),
90
+ global: options.global || false,
91
+ });
74
92
  });
75
93
  program
76
94
  .command("synopsis")
@@ -80,6 +98,185 @@ program
80
98
  .action(async (hours, author) => {
81
99
  await synopsisCommand(hours, author);
82
100
  });
101
+ program
102
+ .command("service-manager")
103
+ .description("Manage Service Manager API daemon")
104
+ .argument("[action]", "start, stop, restart, status, serve")
105
+ .option("-p, --port <port>", "Port to run on (default: from config or 3402)")
106
+ .action(async (action, options) => {
107
+ const { serviceManagerCommand } = await import("./commands/service-manager.js");
108
+ await serviceManagerCommand(action, {
109
+ port: options.port ? parseInt(options.port, 10) : undefined
110
+ });
111
+ });
112
+ program
113
+ .command("services")
114
+ .description("Manage services across all GTM projects (interactive TUI or CLI)")
115
+ .argument("[action]", "create, scan, list, status, start, stop, deps, validate, sync-agents, or leave empty for TUI")
116
+ .argument("[service]", "Service name")
117
+ .option("--dry-run", "Preview what would be discovered (for scan) or preview sync changes (for sync-agents)")
118
+ .option("--current", "Sync only current service (for sync-agents)")
119
+ .option("--path <path>", "Path to scan (default: current directory)")
120
+ .option("--force", "Force operation (for stop with dependents)")
121
+ .option("--verbose", "Verbose output")
122
+ .option("--fix", "Auto-repair issues (for validate)")
123
+ .option("--json", "Output JSON (for validate)")
124
+ .option("--skip-ai", "Skip AI tool, just scaffold (for create)")
125
+ .action(async (action, service, options) => {
126
+ // Handle scan action
127
+ if (action === "scan") {
128
+ const { scanServices } = await import("./commands/services-scan.js");
129
+ await scanServices({
130
+ path: options.path,
131
+ dryRun: options.dryRun
132
+ });
133
+ return;
134
+ }
135
+ // Handle dependency actions
136
+ if (action === "deps" || action === "dependencies") {
137
+ const { buildDependencyGraph, visualizeDependencies, validateDependencies } = await import("./lib/service-dependencies.js");
138
+ const fs = await import("fs");
139
+ const servicesConfigPath = path.join(JFL_PATHS.data, "services.json");
140
+ const servicesConfig = JSON.parse(fs.readFileSync(servicesConfigPath, "utf-8"));
141
+ if (service === "validate") {
142
+ const result = validateDependencies(servicesConfig.services);
143
+ if (result.valid) {
144
+ console.log(chalk.green("\n✓ All dependencies valid\n"));
145
+ }
146
+ else {
147
+ console.log(chalk.red("\n✗ Dependency validation failed:\n"));
148
+ result.errors.forEach(err => console.log(chalk.red(` - ${err}`)));
149
+ console.log();
150
+ }
151
+ }
152
+ else {
153
+ console.log(visualizeDependencies(servicesConfig.services));
154
+ }
155
+ return;
156
+ }
157
+ // If no action, launch interactive TUI
158
+ if (!action) {
159
+ const { spawn } = await import("child_process");
160
+ const { fileURLToPath } = await import("url");
161
+ const __filename = fileURLToPath(import.meta.url);
162
+ const __dirname = path.dirname(__filename);
163
+ const tui = spawn(process.execPath, [
164
+ path.join(__dirname, "../dist/ui/services-manager.js")
165
+ ], {
166
+ stdio: "inherit"
167
+ });
168
+ tui.on("exit", (code) => {
169
+ process.exit(code || 0);
170
+ });
171
+ }
172
+ else {
173
+ // CLI mode
174
+ const { servicesCommand } = await import("./commands/services.js");
175
+ await servicesCommand(action, service, {
176
+ fix: options.fix,
177
+ json: options.json,
178
+ dryRun: options.dryRun,
179
+ current: options.current,
180
+ skipAI: options.skipAi
181
+ });
182
+ }
183
+ });
184
+ program
185
+ .command("onboard <path-or-url>")
186
+ .description("Onboard a service repo as a service agent")
187
+ .option("-n, --name <name>", "Override service name")
188
+ .option("-t, --type <type>", "Override service type (web, api, container, worker, cli, infrastructure, library)")
189
+ .option("-d, --description <desc>", "Override service description")
190
+ .option("--skip-git", "Skip git clone (treat URL as local path)")
191
+ .action(async (pathOrUrl, options) => {
192
+ await onboardCommand(pathOrUrl, options);
193
+ });
194
+ program
195
+ .command("orchestrate [name]")
196
+ .description("Execute multi-service orchestration workflows")
197
+ .option("--dry-run", "Preview orchestration steps without executing")
198
+ .option("--list", "List available orchestrations")
199
+ .option("--create <name>", "Create new orchestration template")
200
+ .action(async (name, options) => {
201
+ const { orchestrate, listOrchestrations, createOrchestration } = await import("./commands/orchestrate.js");
202
+ if (options.list) {
203
+ await listOrchestrations();
204
+ }
205
+ else if (options.create) {
206
+ await createOrchestration(options.create);
207
+ }
208
+ else if (name) {
209
+ await orchestrate(name, { dryRun: options.dryRun });
210
+ }
211
+ else {
212
+ await listOrchestrations();
213
+ }
214
+ });
215
+ program
216
+ .command("dashboard")
217
+ .description("Launch interactive service monitoring dashboard")
218
+ .action(async () => {
219
+ const { startDashboard } = await import("./ui/service-dashboard.js");
220
+ await startDashboard();
221
+ });
222
+ program
223
+ .command("service-agent <action> [name]")
224
+ .description("Manage service MCP agents (init, generate, register, list)")
225
+ .action(async (action, name) => {
226
+ const { init, generate, generateAll, register, unregister, list, clean } = await import("./commands/service-agent.js");
227
+ switch (action) {
228
+ case "init":
229
+ await init(name); // name is optional path
230
+ break;
231
+ case "generate":
232
+ if (!name) {
233
+ console.log(chalk.red("Error: service name required"));
234
+ console.log(chalk.gray("Usage: jfl service-agent generate <service-name>"));
235
+ process.exit(1);
236
+ }
237
+ await generate(name);
238
+ break;
239
+ case "generate-all":
240
+ await generateAll();
241
+ break;
242
+ case "register":
243
+ await register(name);
244
+ break;
245
+ case "unregister":
246
+ if (!name) {
247
+ console.log(chalk.red("Error: service name required"));
248
+ console.log(chalk.gray("Usage: jfl service-agent unregister <service-name>"));
249
+ process.exit(1);
250
+ }
251
+ await unregister(name);
252
+ break;
253
+ case "list":
254
+ await list();
255
+ break;
256
+ case "clean":
257
+ await clean();
258
+ break;
259
+ default:
260
+ console.log(chalk.red(`Unknown action: ${action}`));
261
+ console.log(chalk.gray("Available actions: init, generate, generate-all, register, unregister, list, clean"));
262
+ process.exit(1);
263
+ }
264
+ });
265
+ program
266
+ .command("profile [action]")
267
+ .description("Manage your JFL profile (stored in config)")
268
+ .argument("[action]", "show, edit, export, import, generate")
269
+ .option("-f, --file <path>", "File path for export/import/generate output")
270
+ .action(async (action, options) => {
271
+ await profileCommand(action, options);
272
+ });
273
+ program
274
+ .command("migrate-services")
275
+ .description("Migrate services from references/ to service manager")
276
+ .argument("[gtm-path]", "Path to GTM project (default: current directory)")
277
+ .action(async (gtmPath) => {
278
+ await migrateServices(gtmPath);
279
+ });
83
280
  // ============================================================================
84
281
  // PLATFORM COMMANDS (require login for full features)
85
282
  // ============================================================================
@@ -100,6 +297,28 @@ program
100
297
  logout();
101
298
  console.log(chalk.green("Logged out successfully."));
102
299
  });
300
+ program
301
+ .command("preferences")
302
+ .description("Manage JFL preferences")
303
+ .option("--clear-ai", "Clear saved AI CLI preference")
304
+ .option("--show", "Show current preferences")
305
+ .action(async (options) => {
306
+ const { getConfigValue, deleteConfigKey, getConfig } = await import("./utils/jfl-config.js");
307
+ if (options.clearAi) {
308
+ deleteConfigKey("aiCLI");
309
+ console.log(chalk.green("\n✓ Cleared AI CLI preference"));
310
+ console.log(chalk.gray(" Next 'jfl' will show selection menu\n"));
311
+ return;
312
+ }
313
+ if (options.show || !options.clearAi) {
314
+ console.log(chalk.bold("\n⚙️ JFL Preferences\n"));
315
+ console.log(chalk.gray("AI CLI:") + " " + (getConfigValue("aiCLI") || chalk.gray("none")));
316
+ console.log(chalk.gray("Projects tracked:") + " " + ((getConfigValue("projects") || []).length));
317
+ console.log();
318
+ console.log(chalk.gray("To clear AI preference: jfl preferences --clear-ai"));
319
+ console.log();
320
+ }
321
+ });
103
322
  program
104
323
  .command("wallet")
105
324
  .description("Show wallet and day pass status")
@@ -282,6 +501,38 @@ voice
282
501
  });
283
502
  });
284
503
  // ============================================================================
504
+ // MEMORY SYSTEM (work offline)
505
+ // ============================================================================
506
+ const memory = program.command("memory").description("Memory system management");
507
+ memory
508
+ .command("init")
509
+ .description("Initialize memory database")
510
+ .action(memoryInitCommand);
511
+ memory
512
+ .command("status")
513
+ .description("Show memory statistics")
514
+ .action(memoryStatusCommand);
515
+ memory
516
+ .command("search <query>")
517
+ .description("Search memories")
518
+ .option("-t, --type <type>", "Filter by type (feature, fix, decision, etc.)")
519
+ .option("-n, --max <n>", "Maximum results", "10")
520
+ .action(memorySearchCommand);
521
+ memory
522
+ .command("index")
523
+ .description("Reindex journal entries")
524
+ .option("-f, --force", "Force full reindex")
525
+ .action(memoryIndexCommand);
526
+ // Alias: jfl ask <question> → jfl memory search <question>
527
+ program
528
+ .command("ask <question>")
529
+ .description("Ask a question - searches memory system")
530
+ .option("-t, --type <type>", "Filter by type (feature, fix, decision, etc.)")
531
+ .option("-n, --max <n>", "Maximum results", "5")
532
+ .action(async (question, options) => {
533
+ await memorySearchCommand(question, options);
534
+ });
535
+ // ============================================================================
285
536
  // SKILL SHORTCUTS (work offline)
286
537
  // ============================================================================
287
538
  program
@@ -320,86 +571,6 @@ program
320
571
  await ralphCommand(args);
321
572
  });
322
573
  // ============================================================================
323
- // SESSION MANAGEMENT (multi-platform sessions)
324
- // ============================================================================
325
- const session = program
326
- .command("session")
327
- .description("Manage GTM sessions across platforms (CLI, Telegram, Slack, Web)");
328
- session
329
- .command("create")
330
- .description("Create or get existing session")
331
- .requiredOption("-p, --platform <platform>", "Platform (cli, telegram, slack, web)")
332
- .option("-t, --thread <id>", "Thread/channel ID")
333
- .option("-u, --user <name>", "User name")
334
- .action(async (options) => {
335
- try {
336
- const sessionId = await sessionCreate({
337
- platform: options.platform,
338
- thread: options.thread,
339
- user: options.user
340
- });
341
- console.log(sessionId);
342
- }
343
- catch (error) {
344
- console.error(chalk.red(`Error: ${error.message}`));
345
- process.exit(1);
346
- }
347
- });
348
- session
349
- .command("exec")
350
- .description("Execute command in session context")
351
- .argument("<sessionId>", "Session ID")
352
- .argument("<command>", "Command to execute")
353
- .action(async (sessionId, command) => {
354
- try {
355
- const output = await sessionExec(sessionId, command);
356
- console.log(output);
357
- }
358
- catch (error) {
359
- console.error(chalk.red(`Error: ${error.message}`));
360
- process.exit(1);
361
- }
362
- });
363
- session
364
- .command("list")
365
- .description("List all active sessions")
366
- .action(async () => {
367
- try {
368
- await sessionList();
369
- }
370
- catch (error) {
371
- console.error(chalk.red(`Error: ${error.message}`));
372
- process.exit(1);
373
- }
374
- });
375
- session
376
- .command("info")
377
- .description("Show session information")
378
- .argument("<sessionId>", "Session ID")
379
- .action(async (sessionId) => {
380
- try {
381
- await sessionInfo(sessionId);
382
- }
383
- catch (error) {
384
- console.error(chalk.red(`Error: ${error.message}`));
385
- process.exit(1);
386
- }
387
- });
388
- session
389
- .command("destroy")
390
- .description("Destroy session")
391
- .argument("<sessionId>", "Session ID")
392
- .option("-f, --force", "Force destroy even with uncommitted changes")
393
- .action(async (sessionId, options) => {
394
- try {
395
- await sessionDestroy(sessionId, { force: options.force });
396
- }
397
- catch (error) {
398
- console.error(chalk.red(`Error: ${error.message}`));
399
- process.exit(1);
400
- }
401
- });
402
- // ============================================================================
403
574
  // TEST MODE (for development)
404
575
  // ============================================================================
405
576
  program
@@ -420,63 +591,140 @@ program
420
591
  // ============================================================================
421
592
  // CLAWDBOT INTEGRATION
422
593
  // ============================================================================
423
- program
424
- .command("clawdbot")
425
- .description("Install JFL skill for Clawdbot")
426
- .action(() => {
427
- try {
428
- // Check if clawdbot is installed
429
- execSync("which clawdbot", { stdio: "pipe" });
430
- }
431
- catch {
432
- console.log(chalk.red("\n❌ Clawdbot not installed"));
433
- console.log(chalk.gray(" Install Clawdbot first: https://clawd.bot\n"));
434
- process.exit(1);
435
- }
436
- const __filename = fileURLToPath(import.meta.url);
437
- const __dirname = join(__filename, "..");
438
- const skillsDir = join(homedir(), ".clawdbot/skills");
439
- const targetPath = join(skillsDir, "jfl-gtm");
440
- // Find the skill source (either in node_modules or local dev)
441
- let skillSource = null;
442
- // Try node_modules first (installed via npm)
443
- const npmSkillPath = join(__dirname, "../clawdbot-skill");
444
- if (existsSync(npmSkillPath)) {
445
- skillSource = npmSkillPath;
446
- }
447
- if (!skillSource) {
448
- console.log(chalk.red("\n❌ JFL Clawdbot skill not found"));
449
- console.log(chalk.gray(" This shouldn't happen. Please report a bug.\n"));
450
- process.exit(1);
451
- }
452
- // Create .clawdbot/skills directory if it doesn't exist
453
- if (!existsSync(skillsDir)) {
454
- mkdirSync(skillsDir, { recursive: true });
455
- }
456
- // Remove existing symlink if present
457
- if (existsSync(targetPath)) {
458
- try {
459
- unlinkSync(targetPath);
460
- }
461
- catch (error) {
462
- console.log(chalk.yellow("⚠️ Could not remove existing skill (continuing)"));
463
- }
464
- }
465
- // Create symlink
466
- try {
467
- symlinkSync(skillSource, targetPath);
468
- console.log(chalk.green("\n✓ JFL skill installed for Clawdbot"));
469
- console.log(chalk.gray(" Clawdbot will auto-detect the skill"));
470
- console.log(chalk.cyan("\n Ready! Use /jfl in Telegram/Slack/Discord\n"));
471
- }
472
- catch (error) {
473
- console.log(chalk.red(`\n❌ Failed to install skill: ${error.message}\n`));
474
- process.exit(1);
475
- }
594
+ const clawdbot = program.command("clawdbot").description("Manage JFL plugin for Clawdbot gateway");
595
+ clawdbot
596
+ .command("setup")
597
+ .description("Install JFL plugin into Clawdbot and configure it")
598
+ .action(clawdbotSetupCommand);
599
+ clawdbot
600
+ .command("status")
601
+ .description("Show JFL Clawdbot plugin installation status")
602
+ .action(clawdbotStatusCommand);
603
+ // Default action: show status
604
+ clawdbot.action(clawdbotStatusCommand);
605
+ // ============================================================================
606
+ // OPENCLAW (runtime-agnostic agent protocol)
607
+ // ============================================================================
608
+ const openclaw = program.command("openclaw").description("OpenClaw agent protocol - runtime-agnostic JFL integration");
609
+ openclaw
610
+ .command("session-start")
611
+ .description("Start an agent session (branch, auto-commit, Context Hub)")
612
+ .requiredOption("-a, --agent <name>", "Agent name/ID")
613
+ .option("-g, --gtm <path>", "GTM workspace path")
614
+ .option("--json", "Output JSON")
615
+ .action(async (options) => {
616
+ const { sessionStartCommand } = await import("./commands/openclaw.js");
617
+ await sessionStartCommand(options);
618
+ });
619
+ openclaw
620
+ .command("session-end")
621
+ .description("End session (commit, merge, cleanup)")
622
+ .option("-s, --sync", "Sync to GTM parent (for services)")
623
+ .option("--json", "Output JSON")
624
+ .action(async (options) => {
625
+ const { sessionEndCommand } = await import("./commands/openclaw.js");
626
+ await sessionEndCommand(options);
627
+ });
628
+ openclaw
629
+ .command("heartbeat")
630
+ .description("Health pulse (auto-commit, check Context Hub)")
631
+ .option("--json", "Output JSON")
632
+ .action(async (options) => {
633
+ const { heartbeatCommand: openclawHeartbeat } = await import("./commands/openclaw.js");
634
+ await openclawHeartbeat(options);
635
+ });
636
+ openclaw
637
+ .command("context")
638
+ .description("Get unified context from Context Hub")
639
+ .option("-q, --query <query>", "Search query")
640
+ .option("-t, --task-type <type>", "Task type (code, spec, content, strategy, general)")
641
+ .option("--json", "Output JSON")
642
+ .action(async (options) => {
643
+ const { contextCommand } = await import("./commands/openclaw.js");
644
+ await contextCommand(options);
645
+ });
646
+ openclaw
647
+ .command("journal")
648
+ .description("Write a journal entry")
649
+ .requiredOption("--type <type>", "Entry type (feature, fix, decision, milestone, spec, discovery)")
650
+ .requiredOption("--title <title>", "Entry title")
651
+ .requiredOption("--summary <summary>", "Entry summary")
652
+ .option("--detail <detail>", "Full detail")
653
+ .option("--files <files>", "Comma-separated file paths")
654
+ .option("--json", "Output JSON")
655
+ .action(async (options) => {
656
+ const { journalCommand } = await import("./commands/openclaw.js");
657
+ await journalCommand(options);
658
+ });
659
+ openclaw
660
+ .command("status")
661
+ .description("Show agent session state and health")
662
+ .option("--json", "Output JSON")
663
+ .action(async (options) => {
664
+ const { statusCommand: openclawStatus } = await import("./commands/openclaw.js");
665
+ await openclawStatus(options);
666
+ });
667
+ openclaw
668
+ .command("gtm-list")
669
+ .description("List registered GTM workspaces")
670
+ .option("--json", "Output JSON")
671
+ .action(async (options) => {
672
+ const { gtmListCommand } = await import("./commands/openclaw.js");
673
+ await gtmListCommand(options);
674
+ });
675
+ openclaw
676
+ .command("gtm-switch")
677
+ .description("Switch active GTM workspace")
678
+ .argument("<gtm-id>", "GTM ID to switch to")
679
+ .option("--json", "Output JSON")
680
+ .action(async (gtmId, options) => {
681
+ const { gtmSwitchCommand } = await import("./commands/openclaw.js");
682
+ await gtmSwitchCommand(gtmId, options);
683
+ });
684
+ openclaw
685
+ .command("gtm-create")
686
+ .description("Create and register a new GTM workspace")
687
+ .argument("<name>", "GTM workspace name")
688
+ .option("-p, --path <dir>", "Target directory")
689
+ .option("--json", "Output JSON")
690
+ .action(async (name, options) => {
691
+ const { gtmCreateCommand } = await import("./commands/openclaw.js");
692
+ await gtmCreateCommand(name, options);
693
+ });
694
+ openclaw
695
+ .command("register")
696
+ .description("Register agent with a GTM workspace")
697
+ .requiredOption("-g, --gtm <path>", "GTM workspace path")
698
+ .option("-a, --agent <name>", "Agent name (auto-detected from manifest)")
699
+ .option("--json", "Output JSON")
700
+ .action(async (options) => {
701
+ const { registerCommand } = await import("./commands/openclaw.js");
702
+ await registerCommand(options);
703
+ });
704
+ openclaw
705
+ .command("tag")
706
+ .description("Send message to a service agent")
707
+ .argument("<service>", "Service name")
708
+ .argument("<message>", "Message to send")
709
+ .option("--json", "Output JSON")
710
+ .action(async (service, message, options) => {
711
+ const { tagCommand } = await import("./commands/openclaw.js");
712
+ await tagCommand(service, message, options);
476
713
  });
477
714
  // ============================================================================
478
715
  // HELP
479
716
  // ============================================================================
717
+ // GTM COMMANDS
718
+ // ============================================================================
719
+ const gtm = program.command("gtm").description("GTM workspace management");
720
+ gtm
721
+ .command("process-service-update [event-file]")
722
+ .description("Process service sync notification (called by hooks)")
723
+ .action(async (eventFile) => {
724
+ const { gtmProcessUpdate } = await import("./commands/gtm-process-update.js");
725
+ await gtmProcessUpdate(eventFile);
726
+ });
727
+ // ============================================================================
480
728
  program
481
729
  .command("help")
482
730
  .description("Show help")
@@ -486,14 +734,20 @@ program
486
734
  console.log(chalk.cyan(" Free Tier (works offline):"));
487
735
  console.log(" jfl init Initialize project");
488
736
  console.log(" jfl repair Repair missing .jfl directory");
737
+ console.log(" jfl validate-settings Validate .claude/settings.json");
489
738
  console.log(" jfl update Pull latest JFL updates");
739
+ console.log(" jfl profile Manage your profile");
740
+ console.log(" jfl profile generate Generate CLAUDE.md w/ AI");
490
741
  console.log(" jfl hud Project dashboard");
491
742
  console.log(" jfl status Project status");
743
+ console.log(" jfl onboard Onboard service as agent");
744
+ console.log(" jfl services Manage services");
492
745
  console.log(" jfl brand Brand architect");
493
746
  console.log(" jfl content Content creator");
494
747
  console.log(" jfl voice Voice input commands");
495
748
  console.log(" jfl ralph AI agent loop (ralph-tui)");
496
749
  console.log(" jfl context-hub Context Hub (unified AI context)");
750
+ console.log(" jfl openclaw OpenClaw agent protocol");
497
751
  console.log(" jfl test Test onboarding (isolated)");
498
752
  console.log(chalk.cyan("\n Platform (requires login):"));
499
753
  console.log(" jfl login Login to platform");