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
@@ -1,25 +1,17 @@
1
1
  import chalk from "chalk";
2
- import inquirer from "inquirer";
2
+ import ora from "ora";
3
3
  import * as p from "@clack/prompts";
4
- import { execSync, spawn } from "child_process";
5
- import { existsSync, readFileSync } from "fs";
4
+ import { existsSync } from "fs";
6
5
  import { join } from "path";
6
+ import { homedir } from "os";
7
7
  import Conf from "conf";
8
- import { ensureDayPass, isTrialMode, showDayPassStatus, markTeammateJoined } from "../utils/auth-guard.js";
9
- import { authenticateWithGitHub, discoverJflProjects, cloneRepository, } from "../utils/github-auth.js";
10
- import { renderBanner, showHowItWorksNotice, theme } from "../ui/index.js";
8
+ import { ensureDayPass, isTrialMode } from "../utils/auth-guard.js";
9
+ import { ensureContextHub, getContextHubConfig } from "../utils/ensure-context-hub.js";
10
+ import { isRunning as getContextHubStatus } from "./context-hub.js";
11
11
  import { initCommand } from "./init.js";
12
+ import axios from "axios";
12
13
  const config = new Conf({ projectName: "jfl" });
13
- // Flags for running in autonomous/yolo mode
14
- const AUTONOMOUS_FLAGS = {
15
- claude: "--dangerously-skip-permissions",
16
- codex: "--full-auto",
17
- aider: "--yes-always",
18
- none: undefined,
19
- };
20
- // Flag for enabling Chrome/browser capabilities (Claude only)
21
- const CHROME_FLAG = "--chrome";
22
- export async function sessionCommand() {
14
+ export async function sessionCommand(options = {}) {
23
15
  const cwd = process.cwd();
24
16
  // Check if in a JFL project
25
17
  const hasJflConfig = existsSync(join(cwd, "CLAUDE.md")) || existsSync(join(cwd, "knowledge"));
@@ -32,7 +24,6 @@ export async function sessionCommand() {
32
24
  console.log(chalk.yellow("\nšŸ’³ Payment required (teammates detected)\n"));
33
25
  const dayPass = await ensureDayPass();
34
26
  if (!dayPass) {
35
- // User cancelled or failed to purchase day pass
36
27
  console.log(chalk.red("\nāŒ Cannot start session without active Day Pass\n"));
37
28
  console.log(chalk.gray("Run: jfl login --x402"));
38
29
  console.log();
@@ -49,591 +40,82 @@ export async function sessionCommand() {
49
40
  projects.push(cwd);
50
41
  config.set("projects", projects);
51
42
  }
52
- // Check for saved preference
53
- let preferredCLI = config.get("aiCLI");
54
- // Detect available CLIs
55
- const available = detectAICLIs();
56
- if (available.length === 0) {
57
- await onboardAICLI();
58
- return;
59
- }
60
- // If preference is set and still available, use it
61
- if (preferredCLI) {
62
- const preferred = available.find(cli => cli.command === preferredCLI);
63
- if (preferred) {
64
- await launchCLI(preferred, cwd);
65
- return;
66
- }
67
- }
68
- // If only one option, use it
69
- if (available.length === 1) {
70
- config.set("aiCLI", available[0].command);
71
- await launchCLI(available[0], cwd);
72
- return;
73
- }
74
- // Multiple options - let them choose
75
- console.log(chalk.bold("\nšŸ¤– JFL - AI Session\n"));
76
- console.log(chalk.gray("Multiple AI CLIs detected:\n"));
77
- const { selected } = await inquirer.prompt([
78
- {
79
- type: "list",
80
- name: "selected",
81
- message: "Which AI do you want to use?",
82
- choices: available.map(cli => ({
83
- name: `${cli.name}${cli.version ? ` (${cli.version})` : ""}`,
84
- value: cli.command,
85
- })),
86
- },
87
- ]);
88
- const { remember } = await inquirer.prompt([
89
- {
90
- type: "confirm",
91
- name: "remember",
92
- message: "Remember this choice?",
93
- default: true,
94
- },
95
- ]);
96
- if (remember) {
97
- config.set("aiCLI", selected);
98
- }
99
- const cli = available.find(c => c.command === selected);
100
- await launchCLI(cli, cwd);
101
- }
102
- function detectAICLIs() {
103
- const clis = [];
104
- // Claude Code
105
- try {
106
- const version = execSync("claude --version 2>/dev/null", { encoding: "utf-8" }).trim();
107
- clis.push({
108
- name: "Claude Code",
109
- command: "claude",
110
- provider: "claude",
111
- version: version.split("\n")[0],
112
- });
113
- }
114
- catch {
115
- // Not installed
116
- }
117
- // OpenAI Codex CLI
118
- try {
119
- const version = execSync("codex --version 2>/dev/null", { encoding: "utf-8" }).trim();
120
- clis.push({
121
- name: "Codex CLI",
122
- command: "codex",
123
- provider: "codex",
124
- version,
125
- });
126
- }
127
- catch {
128
- // Not installed
129
- }
130
- // Aider
131
- try {
132
- const version = execSync("aider --version 2>/dev/null", { encoding: "utf-8" }).trim();
133
- clis.push({
134
- name: "Aider",
135
- command: "aider",
136
- provider: "aider",
137
- version,
138
- });
139
- }
140
- catch {
141
- // Not installed
142
- }
143
- return clis;
43
+ // Show JFL Gateway Dashboard
44
+ await showGatewayDashboard();
144
45
  }
145
- async function promptAutonomousMode(cli) {
146
- const savedPref = config.get(`autonomous_${cli.provider}`);
147
- // If they've already set a preference, use it
148
- if (savedPref !== undefined) {
149
- return savedPref;
150
- }
151
- const flag = AUTONOMOUS_FLAGS[cli.provider];
152
- if (!flag)
153
- return false;
154
- console.log();
155
- const { autonomous } = await inquirer.prompt([
156
- {
157
- type: "confirm",
158
- name: "autonomous",
159
- message: `Run in autonomous mode? (${flag})`,
160
- default: false,
161
- },
162
- ]);
163
- if (autonomous) {
164
- console.log(chalk.yellow("\nāš ļø Autonomous mode: AI can execute without asking permission."));
165
- }
166
- const { remember } = await inquirer.prompt([
167
- {
168
- type: "confirm",
169
- name: "remember",
170
- message: "Remember this choice?",
171
- default: true,
172
- },
173
- ]);
174
- if (remember) {
175
- config.set(`autonomous_${cli.provider}`, autonomous);
176
- }
177
- return autonomous;
178
- }
179
- async function promptChromeMode(cli) {
180
- // Chrome mode only available for Claude
181
- if (cli.provider !== "claude")
182
- return false;
183
- const savedPref = config.get("chrome_claude");
184
- // If they've already set a preference, use it
185
- if (savedPref !== undefined) {
186
- return savedPref;
187
- }
188
- console.log();
189
- const { chrome } = await inquirer.prompt([
190
- {
191
- type: "confirm",
192
- name: "chrome",
193
- message: `Enable browser capabilities? (${CHROME_FLAG})`,
194
- default: false,
195
- },
196
- ]);
197
- if (chrome) {
198
- console.log(chalk.cyan("\n🌐 Chrome mode: Claude can browse and interact with web pages."));
199
- }
200
- const { remember } = await inquirer.prompt([
201
- {
202
- type: "confirm",
203
- name: "remember",
204
- message: "Remember this choice?",
205
- default: true,
206
- },
207
- ]);
208
- if (remember) {
209
- config.set("chrome_claude", chrome);
210
- }
211
- return chrome;
212
- }
213
- function showBanner() {
214
- // Get version from package.json
215
- let version;
216
- try {
217
- const pkgPath = new URL("../../package.json", import.meta.url);
218
- const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
219
- version = pkg.version;
220
- }
221
- catch {
222
- // Ignore
223
- }
224
- console.log(renderBanner({ version }));
225
- }
226
- async function launchCLI(cli, cwd, skipAutonomousPrompt = false) {
227
- // Check for autonomous mode
228
- let autonomous = false;
229
- if (!skipAutonomousPrompt) {
230
- autonomous = await promptAutonomousMode(cli);
46
+ async function showGatewayDashboard() {
47
+ console.log(chalk.bold.cyan("\nā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”"));
48
+ console.log(chalk.bold.cyan("│ JFL Gateway Dashboard │"));
49
+ console.log(chalk.bold.cyan("ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜\n"));
50
+ // 1. Ensure and check Context Hub
51
+ const spinner1 = ora("Checking Context Hub...").start();
52
+ await ensureContextHub();
53
+ const contextHubConfig = getContextHubConfig();
54
+ const contextHubStatus = getContextHubStatus(contextHubConfig.mode === "global" ? homedir() : process.cwd());
55
+ if (contextHubStatus.running) {
56
+ spinner1.succeed(chalk.green("Context Hub") +
57
+ chalk.gray(` (${contextHubConfig.mode} mode, port ${contextHubConfig.port}, PID ${contextHubStatus.pid})`));
231
58
  }
232
59
  else {
233
- autonomous = config.get(`autonomous_${cli.provider}`) || false;
234
- }
235
- // Check for chrome mode (Claude only)
236
- let chrome = false;
237
- if (cli.provider === "claude") {
238
- if (!skipAutonomousPrompt) {
239
- chrome = await promptChromeMode(cli);
240
- }
241
- else {
242
- chrome = config.get("chrome_claude") || false;
243
- }
244
- }
245
- // Build args array
246
- const args = [];
247
- if (autonomous && AUTONOMOUS_FLAGS[cli.provider]) {
248
- args.push(AUTONOMOUS_FLAGS[cli.provider]);
60
+ spinner1.fail(chalk.red("Context Hub not running"));
249
61
  }
250
- if (chrome) {
251
- args.push(CHROME_FLAG);
252
- }
253
- // Show trial/day pass status (no banner - already shown in onboard)
254
- if (isTrialMode()) {
255
- console.log(theme.success("šŸŽ Trial Mode") + theme.dim(" — Free until foundation complete\n"));
62
+ // 2. Check Service Manager
63
+ const spinner2 = ora("Checking Service Manager...").start();
64
+ const serviceManagerStatus = await checkServiceManager();
65
+ if (serviceManagerStatus.running) {
66
+ spinner2.succeed(chalk.green("Service Manager") +
67
+ chalk.gray(` (port 3401, ${serviceManagerStatus.services} services)`));
256
68
  }
257
69
  else {
258
- showDayPassStatus();
259
- console.log();
70
+ spinner2.warn(chalk.yellow("Service Manager not running"));
71
+ console.log(chalk.gray(" Start with: pm2 start ~/.jfl/service-manager/ecosystem.config.js"));
260
72
  }
261
- // Build mode indicators
262
- const modes = [];
263
- if (autonomous)
264
- modes.push("autonomous");
265
- if (chrome)
266
- modes.push("chrome");
267
- const modeStr = modes.length > 0 ? theme.dim(` (${modes.join(", ")})`) : "";
268
- console.log(theme.accent(`Launching ${cli.name}`) + modeStr);
269
- console.log(theme.dim("Context loaded from CLAUDE.md + knowledge/\n"));
270
- console.log(theme.dimmer("─".repeat(50)));
73
+ // 3. Show connection info
271
74
  console.log();
272
- // Spawn the CLI in the current directory
273
- const child = spawn(cli.command, args, {
274
- cwd,
275
- stdio: "inherit",
276
- env: {
277
- ...process.env,
278
- JFL_PROJECT: cwd,
279
- },
280
- });
281
- child.on("error", (err) => {
282
- console.error(chalk.red(`\nFailed to launch ${cli.name}:`), err.message);
283
- });
284
- child.on("exit", (code) => {
285
- if (code !== 0 && code !== null) {
286
- console.log(chalk.yellow(`\n${cli.name} exited with code ${code}`));
287
- }
288
- console.log(chalk.gray("\nJFL session ended.\n"));
289
- });
290
- }
291
- async function onboardNewUser(cwd) {
292
- // Show banner with version
293
- showBanner();
294
- // Show "How It Works" notice
295
- showHowItWorksNotice();
296
- // Check for known projects first
297
- const knownProjects = config.get("projects") || [];
298
- const existingProjects = knownProjects.filter((p) => existsSync(join(p, "CLAUDE.md")) || existsSync(join(p, "knowledge")));
299
- // Start Clawdbot-style flow
300
- p.intro(chalk.hex("#FFD700")("ā”Œ JFL onboarding"));
301
- // If we have known projects, show them upfront
302
- if (existingProjects.length > 0) {
303
- const selected = await p.select({
304
- message: "Open a project or create new?",
305
- options: [
306
- ...existingProjects.map((proj) => ({
307
- label: proj.replace(process.env.HOME || "", "~"),
308
- value: proj,
309
- })),
310
- { label: "Join existing project (I was invited)", value: "join" },
311
- { label: "Create new project", value: "new" },
312
- ],
313
- });
314
- if (p.isCancel(selected)) {
315
- p.cancel("Setup cancelled.");
316
- process.exit(0);
317
- }
318
- if (selected === "join") {
319
- await joinExistingProject();
320
- return;
321
- }
322
- if (selected !== "new") {
323
- // Update config with cleaned list
324
- config.set("projects", existingProjects);
325
- process.chdir(selected);
326
- p.outro(chalk.hex("#FFA500")(`Opening ${selected.replace(process.env.HOME || "", "~")}`));
327
- // Launch
328
- const available = detectAICLIs();
329
- if (available.length > 0) {
330
- await launchCLI(available[0], selected);
331
- }
332
- else {
333
- await onboardAICLI();
334
- }
335
- return;
336
- }
337
- }
338
- // No known projects or they want to create new
339
- const action = await p.select({
340
- message: "What do you want to do?",
341
- options: [
342
- { label: "Join existing project (I was invited)", value: "join" },
343
- { label: "Create a new project", value: "create" },
344
- ],
345
- });
346
- if (p.isCancel(action)) {
347
- p.cancel("Setup cancelled.");
348
- process.exit(0);
349
- }
350
- if (action === "join") {
351
- await joinExistingProject();
352
- return;
353
- }
354
- // Redirect to init command for proper project creation
355
- p.outro(chalk.hex("#FFA500")("Launching project setup..."));
356
- await initCommand();
357
- }
358
- async function joinExistingProject() {
359
- console.log(chalk.cyan("\nšŸ”— Join Existing Project\n"));
360
- // Authenticate with GitHub using Device Flow
361
- let username;
362
- try {
363
- username = await authenticateWithGitHub();
364
- }
365
- catch (error) {
366
- console.error(chalk.red("\nGitHub authentication failed"));
367
- console.error(chalk.gray(error instanceof Error ? error.message : String(error)));
368
- return;
369
- }
370
- // Discover JFL projects
371
- let projects;
372
- try {
373
- projects = await discoverJflProjects();
374
- }
375
- catch (error) {
376
- console.error(chalk.red("\nFailed to discover projects"));
377
- console.error(chalk.gray(error instanceof Error ? error.message : String(error)));
378
- return;
379
- }
380
- if (projects.length === 0) {
381
- console.log(chalk.yellow("\nNo JFL projects found that you have access to.\n"));
382
- console.log(chalk.gray("Ask the project owner to add you as a collaborator."));
383
- console.log(chalk.gray("The project needs a CLAUDE.md file or .jfl/ directory.\n"));
384
- return;
385
- }
386
- // Show projects with details
75
+ console.log(chalk.bold("Gateway Endpoints:"));
76
+ console.log(chalk.gray(" Context Hub: ") + chalk.cyan(`http://localhost:${contextHubConfig.port}`));
77
+ console.log(chalk.gray(" Service Manager: ") + chalk.cyan("http://localhost:3401"));
78
+ console.log(chalk.gray(" MCP Server: ") + chalk.cyan("Connected via MCP"));
79
+ // 4. Show how to connect
387
80
  console.log();
388
- const { selectedProject } = await inquirer.prompt([
389
- {
390
- type: "list",
391
- name: "selectedProject",
392
- message: "Which project do you want to join?",
393
- choices: projects.map((p) => ({
394
- name: `${p.fullName}${p.hasUserSuggestions ? chalk.green(" (you're invited)") : ""}${p.description ? chalk.gray(` - ${p.description}`) : ""}`,
395
- value: p,
396
- })),
397
- },
398
- ]);
399
- // Check if we already have this project locally
400
- const trackedProjects = config.get("projects") || [];
401
- const existingLocal = trackedProjects.find((p) => {
402
- const projectName = p.split("/").pop();
403
- return projectName === selectedProject.name &&
404
- (existsSync(join(p, "CLAUDE.md")) || existsSync(join(p, ".jfl")));
405
- });
406
- // Also check common locations
407
- const commonPaths = [
408
- join(process.env.HOME || "", "Projects", selectedProject.name),
409
- join(process.env.HOME || "", selectedProject.name),
410
- join(process.cwd(), selectedProject.name),
411
- ];
412
- const existingAtCommonPath = commonPaths.find((p) => existsSync(p) && (existsSync(join(p, "CLAUDE.md")) || existsSync(join(p, ".jfl"))));
413
- const alreadyCloned = existingLocal || existingAtCommonPath;
414
- if (alreadyCloned) {
415
- console.log(chalk.green(`\nāœ“ Already have ${selectedProject.name} at ${alreadyCloned}\n`));
416
- const { openExisting } = await inquirer.prompt([
417
- {
418
- type: "confirm",
419
- name: "openExisting",
420
- message: "Open it?",
421
- default: true,
422
- },
423
- ]);
424
- if (openExisting) {
425
- // Track if not already
426
- if (!trackedProjects.includes(alreadyCloned)) {
427
- trackedProjects.push(alreadyCloned);
428
- config.set("projects", trackedProjects);
429
- }
430
- process.chdir(alreadyCloned);
431
- const available = detectAICLIs();
432
- if (available.length > 0) {
433
- await launchCLI(available[0], alreadyCloned);
434
- }
435
- else {
436
- await onboardAICLI();
437
- }
438
- }
439
- return;
440
- }
441
- // Show project info
81
+ console.log(chalk.bold("AI Tools Connection:"));
82
+ console.log(chalk.gray(" Claude Code connects via MCP automatically"));
83
+ console.log(chalk.gray(" Cursor connects via MCP automatically"));
84
+ console.log(chalk.gray(" Custom tools can use HTTP API"));
85
+ // 5. Show available commands
442
86
  console.log();
443
- console.log(chalk.bold(`Project: ${selectedProject.fullName}`));
444
- if (selectedProject.description) {
445
- console.log(chalk.gray(selectedProject.description));
446
- }
447
- if (selectedProject.projectConfig?.wallet) {
448
- console.log(chalk.gray(`Wallet: ${selectedProject.projectConfig.wallet.slice(0, 10)}...`));
449
- }
450
- if (selectedProject.hasUserSuggestions) {
451
- console.log(chalk.green(`āœ“ Your suggestions file exists (suggestions/${username}.md)`));
452
- }
87
+ console.log(chalk.bold("Manage Services:"));
88
+ console.log(chalk.gray(" jfl-services list ") + "# List all services");
89
+ console.log(chalk.gray(" jfl-services start <id> ") + "# Start a service");
90
+ console.log(chalk.gray(" jfl-services logs <id> ") + "# View service logs");
91
+ console.log();
92
+ console.log(chalk.bold("View Status:"));
93
+ console.log(chalk.gray(" jfl status ") + "# Project status");
94
+ console.log(chalk.gray(" jfl hud ") + "# Campaign dashboard");
453
95
  console.log();
454
- // Ask where to clone
455
- const defaultPath = join(process.env.HOME || "", "Projects", selectedProject.name);
456
- const { clonePath } = await inquirer.prompt([
457
- {
458
- type: "input",
459
- name: "clonePath",
460
- message: "Where to clone?",
461
- default: defaultPath,
462
- },
463
- ]);
464
- const expandedPath = clonePath.replace(/^~/, process.env.HOME || "");
465
- // Clone the repo
466
- let clonedPath;
96
+ console.log(chalk.green("āœ“ JFL Gateway is ready!"));
97
+ console.log(chalk.gray(" Open Claude Code or Cursor to connect via MCP\n"));
98
+ }
99
+ async function checkServiceManager() {
467
100
  try {
468
- clonedPath = await cloneRepository(selectedProject, expandedPath);
469
- }
470
- catch (error) {
471
- console.error(chalk.red("\nClone failed"));
472
- console.error(chalk.gray(error instanceof Error ? error.message : String(error)));
473
- return;
474
- }
475
- // Track this project
476
- const allProjects = config.get("projects") || [];
477
- if (!allProjects.includes(clonedPath)) {
478
- allProjects.push(clonedPath);
479
- config.set("projects", allProjects);
480
- }
481
- config.set("hasOnboarded", true);
482
- // Mark this teammate as joined (adds <!-- joined: DATE --> marker)
483
- markTeammateJoined(username);
484
- console.log(chalk.green(`\nāœ“ Joined ${selectedProject.name}!\n`));
485
- // Show project configuration
486
- if (selectedProject.projectConfig?.wallet) {
487
- console.log(chalk.gray("Project Configuration:"));
488
- console.log(chalk.gray(` Owner: ${selectedProject.projectConfig.walletOwner || selectedProject.owner}`));
489
- console.log(chalk.gray(` Wallet: ${selectedProject.projectConfig.wallet} (configured)`));
490
- console.log(chalk.gray(` Your role: Contributor`));
491
- console.log();
101
+ const response = await axios.get("http://localhost:3401/health", { timeout: 2000 });
102
+ const services = response.data.stats?.total_services || 0;
103
+ return { running: true, services };
492
104
  }
493
- console.log(chalk.gray(`Location: ${clonedPath}`));
494
- console.log(chalk.cyan(`\nTo start working:\n`));
495
- console.log(chalk.white(` cd ${clonedPath}`));
496
- console.log(chalk.white(` jfl\n`));
497
- // Offer to launch now
498
- const { launchNow } = await inquirer.prompt([
499
- {
500
- type: "confirm",
501
- name: "launchNow",
502
- message: "Open project now?",
503
- default: true,
504
- },
505
- ]);
506
- if (launchNow) {
507
- process.chdir(clonedPath);
508
- const available = detectAICLIs();
509
- if (available.length > 0) {
510
- await launchCLI(available[0], clonedPath);
511
- }
512
- else {
513
- await onboardAICLI();
514
- }
105
+ catch (err) {
106
+ return { running: false };
515
107
  }
516
108
  }
517
- async function onboardAICLI() {
518
- console.log(chalk.bold("\nšŸ¤– JFL - Setup AI Assistant\n"));
519
- console.log(chalk.gray("JFL works with your AI of choice. Let's get you set up.\n"));
520
- const { experience } = await inquirer.prompt([
521
- {
522
- type: "list",
523
- name: "experience",
524
- message: "How technical are you?",
525
- choices: [
526
- { name: "I'm a developer - comfortable with terminal", value: "dev" },
527
- { name: "Somewhat technical - can follow instructions", value: "some" },
528
- { name: "Not technical - need the easy path", value: "none" },
529
- ],
530
- },
531
- ]);
532
- if (experience === "none") {
533
- // Non-technical path - recommend browser-based or desktop app
534
- console.log(chalk.cyan("\nšŸ“± Easiest options for you:\n"));
535
- console.log(chalk.bold("1. Claude.ai (browser)"));
536
- console.log(chalk.gray(" Go to claude.ai, sign up, and chat directly"));
537
- console.log(chalk.gray(" You can paste your project files into the chat\n"));
538
- console.log(chalk.bold("2. Claude Desktop App"));
539
- console.log(chalk.gray(" Download from claude.ai/download"));
540
- console.log(chalk.gray(" Works like ChatGPT but with Claude\n"));
541
- console.log(chalk.bold("3. Cursor (AI-powered code editor)"));
542
- console.log(chalk.gray(" Download from cursor.com"));
543
- console.log(chalk.gray(" Like VS Code but with AI built in\n"));
544
- console.log(chalk.yellow("For the full JFL experience, Claude Code is best."));
545
- console.log(chalk.gray("But start with what's comfortable.\n"));
546
- return;
547
- }
548
- // Technical path - CLI tools
549
- console.log(chalk.yellow("\nNo AI CLI detected.\n"));
550
- const { choice } = await inquirer.prompt([
551
- {
552
- type: "list",
553
- name: "choice",
554
- message: "Which AI do you want to use?",
555
- choices: [
556
- {
557
- name: "Claude Code (recommended for JFL)",
558
- value: "claude",
559
- },
560
- {
561
- name: "Codex CLI (OpenAI)",
562
- value: "codex",
563
- },
564
- {
565
- name: "Aider (works with multiple models)",
566
- value: "aider",
567
- },
568
- {
569
- name: "I'll set it up myself",
570
- value: "manual",
571
- },
572
- ],
573
- },
574
- ]);
575
- if (choice === "manual") {
576
- console.log(chalk.gray("\nSupported AI CLIs:"));
577
- console.log(" • Claude Code: npm install -g @anthropic-ai/claude-code");
578
- console.log(" • Codex CLI: npm install -g @openai/codex");
579
- console.log(" • Aider: pip install aider-chat");
580
- console.log(chalk.gray("\nRun 'jfl' again after installing.\n"));
581
- return;
582
- }
583
- const installCommands = {
584
- claude: {
585
- cmd: "npm install -g @anthropic-ai/claude-code",
586
- name: "Claude Code",
587
- },
588
- codex: {
589
- cmd: "npm install -g @openai/codex",
590
- name: "Codex CLI",
591
- },
592
- aider: {
593
- cmd: "pip install aider-chat",
594
- name: "Aider",
595
- },
596
- };
597
- const install = installCommands[choice];
598
- console.log(chalk.cyan(`\nInstalling ${install.name}...\n`));
599
- console.log(chalk.gray(`$ ${install.cmd}\n`));
600
- const { proceed } = await inquirer.prompt([
601
- {
602
- type: "confirm",
603
- name: "proceed",
604
- message: "Run this command?",
605
- default: true,
606
- },
607
- ]);
608
- if (!proceed) {
609
- console.log(chalk.gray(`\nRun manually: ${install.cmd}`));
610
- console.log(chalk.gray("Then run 'jfl' again.\n"));
109
+ async function onboardNewUser(cwd) {
110
+ console.log(chalk.yellow("\nāš ļø Not in a JFL project\n"));
111
+ const shouldInit = await p.confirm({
112
+ message: "Initialize this directory as a JFL project?",
113
+ initialValue: true,
114
+ });
115
+ if (p.isCancel(shouldInit) || !shouldInit) {
116
+ console.log(chalk.gray("\nRun 'jfl init' when ready\n"));
611
117
  return;
612
118
  }
613
- try {
614
- execSync(install.cmd, { stdio: "inherit" });
615
- console.log(chalk.green(`\nāœ“ ${install.name} installed!\n`));
616
- // Prompt for API key setup
617
- if (choice === "claude") {
618
- console.log(chalk.gray("Set your Anthropic API key:"));
619
- console.log(chalk.white(" export ANTHROPIC_API_KEY=your-key-here\n"));
620
- console.log(chalk.gray("Or run 'claude' to authenticate interactively.\n"));
621
- }
622
- else if (choice === "codex") {
623
- console.log(chalk.gray("Set your OpenAI API key:"));
624
- console.log(chalk.white(" export OPENAI_API_KEY=your-key-here\n"));
625
- }
626
- else if (choice === "aider") {
627
- console.log(chalk.gray("Set your API key (Anthropic or OpenAI):"));
628
- console.log(chalk.white(" export ANTHROPIC_API_KEY=your-key-here"));
629
- console.log(chalk.white(" # or"));
630
- console.log(chalk.white(" export OPENAI_API_KEY=your-key-here\n"));
631
- }
632
- console.log(chalk.cyan("Run 'jfl' to start your AI session.\n"));
633
- }
634
- catch (error) {
635
- console.error(chalk.red("\nInstallation failed."));
636
- console.log(chalk.gray(`\nTry manually: ${install.cmd}\n`));
637
- }
119
+ await initCommand();
638
120
  }
639
121
  //# sourceMappingURL=session.js.map