@lobu/cli 3.0.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 (116) hide show
  1. package/README.md +276 -0
  2. package/bin/create-lobu.js +5 -0
  3. package/bin/lobu.js +5 -0
  4. package/dist/api/client.d.ts +11 -0
  5. package/dist/api/client.d.ts.map +1 -0
  6. package/dist/api/client.js +35 -0
  7. package/dist/api/client.js.map +1 -0
  8. package/dist/api/credentials.d.ts +13 -0
  9. package/dist/api/credentials.d.ts.map +1 -0
  10. package/dist/api/credentials.js +39 -0
  11. package/dist/api/credentials.js.map +1 -0
  12. package/dist/commands/dev.d.ts +13 -0
  13. package/dist/commands/dev.d.ts.map +1 -0
  14. package/dist/commands/dev.js +128 -0
  15. package/dist/commands/dev.js.map +1 -0
  16. package/dist/commands/init.d.ts +2 -0
  17. package/dist/commands/init.d.ts.map +1 -0
  18. package/dist/commands/init.js +905 -0
  19. package/dist/commands/init.js.map +1 -0
  20. package/dist/commands/launch.d.ts +6 -0
  21. package/dist/commands/launch.d.ts.map +1 -0
  22. package/dist/commands/launch.js +32 -0
  23. package/dist/commands/launch.js.map +1 -0
  24. package/dist/commands/login.d.ts +4 -0
  25. package/dist/commands/login.d.ts.map +1 -0
  26. package/dist/commands/login.js +29 -0
  27. package/dist/commands/login.js.map +1 -0
  28. package/dist/commands/logout.d.ts +2 -0
  29. package/dist/commands/logout.d.ts.map +1 -0
  30. package/dist/commands/logout.js +7 -0
  31. package/dist/commands/logout.js.map +1 -0
  32. package/dist/commands/providers/add.d.ts +2 -0
  33. package/dist/commands/providers/add.d.ts.map +1 -0
  34. package/dist/commands/providers/add.js +51 -0
  35. package/dist/commands/providers/add.js.map +1 -0
  36. package/dist/commands/providers/list.d.ts +2 -0
  37. package/dist/commands/providers/list.d.ts.map +1 -0
  38. package/dist/commands/providers/list.js +21 -0
  39. package/dist/commands/providers/list.js.map +1 -0
  40. package/dist/commands/secrets.d.ts +8 -0
  41. package/dist/commands/secrets.d.ts.map +1 -0
  42. package/dist/commands/secrets.js +98 -0
  43. package/dist/commands/secrets.js.map +1 -0
  44. package/dist/commands/skills/add.d.ts +2 -0
  45. package/dist/commands/skills/add.d.ts.map +1 -0
  46. package/dist/commands/skills/add.js +47 -0
  47. package/dist/commands/skills/add.js.map +1 -0
  48. package/dist/commands/skills/info.d.ts +2 -0
  49. package/dist/commands/skills/info.d.ts.map +1 -0
  50. package/dist/commands/skills/info.js +45 -0
  51. package/dist/commands/skills/info.js.map +1 -0
  52. package/dist/commands/skills/list.d.ts +2 -0
  53. package/dist/commands/skills/list.d.ts.map +1 -0
  54. package/dist/commands/skills/list.js +30 -0
  55. package/dist/commands/skills/list.js.map +1 -0
  56. package/dist/commands/skills/registry.d.ts +34 -0
  57. package/dist/commands/skills/registry.d.ts.map +1 -0
  58. package/dist/commands/skills/registry.js +38 -0
  59. package/dist/commands/skills/registry.js.map +1 -0
  60. package/dist/commands/skills/search.d.ts +2 -0
  61. package/dist/commands/skills/search.d.ts.map +1 -0
  62. package/dist/commands/skills/search.js +21 -0
  63. package/dist/commands/skills/search.js.map +1 -0
  64. package/dist/commands/status.d.ts +2 -0
  65. package/dist/commands/status.d.ts.map +1 -0
  66. package/dist/commands/status.js +7 -0
  67. package/dist/commands/status.js.map +1 -0
  68. package/dist/commands/validate.d.ts +2 -0
  69. package/dist/commands/validate.d.ts.map +1 -0
  70. package/dist/commands/validate.js +73 -0
  71. package/dist/commands/validate.js.map +1 -0
  72. package/dist/commands/whoami.d.ts +2 -0
  73. package/dist/commands/whoami.d.ts.map +1 -0
  74. package/dist/commands/whoami.js +25 -0
  75. package/dist/commands/whoami.js.map +1 -0
  76. package/dist/config/loader.d.ts +16 -0
  77. package/dist/config/loader.d.ts.map +1 -0
  78. package/dist/config/loader.js +41 -0
  79. package/dist/config/loader.js.map +1 -0
  80. package/dist/config/schema.d.ts +279 -0
  81. package/dist/config/schema.d.ts.map +1 -0
  82. package/dist/config/schema.js +52 -0
  83. package/dist/config/schema.js.map +1 -0
  84. package/dist/config/transformer.d.ts +11 -0
  85. package/dist/config/transformer.d.ts.map +1 -0
  86. package/dist/config/transformer.js +49 -0
  87. package/dist/config/transformer.js.map +1 -0
  88. package/dist/index.d.ts +6 -0
  89. package/dist/index.d.ts.map +1 -0
  90. package/dist/index.js +183 -0
  91. package/dist/index.js.map +1 -0
  92. package/dist/mcp-servers.d.ts +11 -0
  93. package/dist/mcp-servers.d.ts.map +1 -0
  94. package/dist/mcp-servers.js +27 -0
  95. package/dist/mcp-servers.js.map +1 -0
  96. package/dist/mcp-servers.json +216 -0
  97. package/dist/templates/.env.tmpl +29 -0
  98. package/dist/templates/.gitignore.tmpl +32 -0
  99. package/dist/templates/AGENTS.md.tmpl +1 -0
  100. package/dist/templates/Dockerfile.worker.tmpl +29 -0
  101. package/dist/templates/README.md.tmpl +95 -0
  102. package/dist/templates/TESTING.md.tmpl +225 -0
  103. package/dist/templates/lobu.toml.tmpl +44 -0
  104. package/dist/types.d.ts +76 -0
  105. package/dist/types.d.ts.map +1 -0
  106. package/dist/types.js +2 -0
  107. package/dist/types.js.map +1 -0
  108. package/dist/utils/config.d.ts +2 -0
  109. package/dist/utils/config.d.ts.map +1 -0
  110. package/dist/utils/config.js +13 -0
  111. package/dist/utils/config.js.map +1 -0
  112. package/dist/utils/template.d.ts +2 -0
  113. package/dist/utils/template.d.ts.map +1 -0
  114. package/dist/utils/template.js +19 -0
  115. package/dist/utils/template.js.map +1 -0
  116. package/package.json +48 -0
package/README.md ADDED
@@ -0,0 +1,276 @@
1
+ # create-lobu
2
+
3
+ CLI tool for initializing Lobu projects with Docker Compose.
4
+
5
+ ## Installation
6
+
7
+ ### Standalone
8
+
9
+ ```bash
10
+ npm install -g create-lobu
11
+
12
+ mkdir my-lobu
13
+ cd my-lobu
14
+ npm create lobu my-lobu
15
+ docker compose up -d
16
+ ```
17
+
18
+ ### npx/npm create (Recommended)
19
+
20
+ ```bash
21
+ npm create lobu my-lobu
22
+ cd my-lobu
23
+ docker compose up -d
24
+ ```
25
+
26
+ ## Worker Deployment Options
27
+
28
+ Lobu supports two deployment patterns for workers:
29
+
30
+ ### Option 1: Base Image (Day 0 - Quick Start)
31
+
32
+ **Best for:** Beginners, tutorials, quick prototypes
33
+
34
+ ```dockerfile
35
+ # Extends our curated base image
36
+ FROM buremba/lobu-worker-base:0.1.0
37
+
38
+ # Add your customizations
39
+ RUN pip install pandas
40
+ RUN apt-get install postgresql-client
41
+ ```
42
+
43
+ **Pros:**
44
+ - ✅ Turnkey experience - just works
45
+ - ✅ All dependencies pre-installed
46
+ - ✅ Predictable environment
47
+
48
+ **Cons:**
49
+ - ❌ Stuck with our base OS choice
50
+ - ❌ May not meet compliance requirements
51
+
52
+ ---
53
+
54
+ ### Option 2: Package Installation (Day 2 - Advanced)
55
+
56
+ **Best for:** Enterprise, compliance-heavy environments, custom requirements
57
+
58
+ ```dockerfile
59
+ # Use YOUR approved base image
60
+ FROM company-registry/ubuntu:22.04
61
+
62
+ # Install system dependencies
63
+ RUN apt-get update && apt-get install -y \
64
+ nodejs npm git docker.io python3 curl
65
+
66
+ # Install Claude CLI
67
+ RUN curl -L https://claude.ai/install.sh | sh
68
+
69
+ # Install Lobu worker as a package
70
+ RUN npm install -g @lobu/worker@^0.1.0
71
+
72
+ # Your customizations
73
+ COPY ./scripts /workspace/scripts
74
+
75
+ CMD ["lobu-worker"]
76
+ ```
77
+
78
+ **Pros:**
79
+ - ✅ Full control over base OS
80
+ - ✅ Use company-approved images
81
+ - ✅ Smaller images (Alpine, Distroless)
82
+ - ✅ Meet security/compliance requirements
83
+
84
+ **Cons:**
85
+ - ❌ More setup required
86
+ - ❌ Must install system dependencies yourself
87
+
88
+ See [Worker Package Documentation](../worker/docs/custom-base-image.md) for details.
89
+
90
+ ---
91
+
92
+ ## Commands
93
+
94
+ ### `create-lobu`
95
+
96
+ Initialize a new Lobu project in the current directory.
97
+
98
+ **Interactive prompts:**
99
+ - **Worker mode:** Base image vs Package installation
100
+ - Slack credentials
101
+ - Anthropic API key
102
+ - Public gateway URL (for OAuth)
103
+
104
+ **Generates:**
105
+ - `docker-compose.yml` - Service definitions (redis, gateway, worker)
106
+ - `.env` - Credentials
107
+ - `Dockerfile.worker` - Worker customization via Dockerfile
108
+ - `.gitignore`, `README.md`
109
+
110
+ **If docker-compose.yml exists**, you'll be prompted for an alternative filename.
111
+
112
+ ## Usage
113
+
114
+ After running `npm create lobu`:
115
+
116
+ ```bash
117
+ # Start services
118
+ docker compose up -d
119
+
120
+ # View logs
121
+ docker compose logs -f
122
+
123
+ # Stop services
124
+ docker compose down
125
+
126
+ # Rebuild worker after changes
127
+ docker compose build worker
128
+ ```
129
+
130
+ ## Configuration
131
+
132
+ ### Dockerfile.worker (Base Image Mode)
133
+
134
+ ```dockerfile
135
+ FROM buremba/lobu-worker-base:0.1.0
136
+
137
+ # Add system packages
138
+ RUN apt-get update && apt-get install -y postgresql-client
139
+
140
+ # Add Python packages
141
+ RUN pip install pandas matplotlib
142
+
143
+ # Add Node.js packages
144
+ RUN bun add @octokit/rest
145
+
146
+ # Copy custom scripts
147
+ COPY ./scripts /workspace/scripts
148
+ ```
149
+
150
+ ### Dockerfile.worker (Package Mode)
151
+
152
+ ```dockerfile
153
+ # Bring your own base
154
+ FROM node:20-alpine
155
+
156
+ # Install required system dependencies
157
+ RUN apk add --no-cache git docker-cli python3 py3-pip curl
158
+
159
+ # Install Claude CLI
160
+ RUN curl -L https://claude.ai/install.sh | sh
161
+
162
+ # Install worker package
163
+ RUN npm install -g @lobu/worker@^0.1.0
164
+
165
+ # Your customizations
166
+ RUN pip3 install pandas matplotlib
167
+
168
+ CMD ["lobu-worker"]
169
+ ```
170
+
171
+ ## Development Workflow
172
+
173
+ ```bash
174
+ # 1. Create project
175
+ mkdir my-bot
176
+ cd my-bot
177
+ npm create lobu
178
+
179
+ # 2. Choose worker mode during init
180
+ # - Base image (recommended)
181
+ # - Package installation (advanced)
182
+
183
+ # 3. Customize worker (optional)
184
+ # Edit Dockerfile.worker
185
+
186
+ # 4. Start services
187
+ docker compose up -d
188
+
189
+ # 5. View logs
190
+ docker compose logs -f
191
+
192
+ # 6. Rebuild after changes
193
+ docker compose build worker
194
+
195
+ # 7. Stop services
196
+ docker compose down
197
+ ```
198
+
199
+ ## Version Locking
200
+
201
+ The CLI version locks to base image versions:
202
+
203
+ - CLI `0.1.0` → `buremba/lobu-worker-base:0.1.0`
204
+ - CLI `0.2.0` → `buremba/lobu-worker-base:0.2.0`
205
+
206
+ This ensures compatibility between CLI and runtime images.
207
+
208
+ ## Distribution Strategy
209
+
210
+ Lobu uses a dual distribution pattern:
211
+
212
+ **Day 0 (Quick Start):**
213
+ - Use `buremba/lobu-worker-base` Docker image
214
+ - Extend with Dockerfile
215
+ - Perfect for learning, prototypes
216
+
217
+ **Day 2+ (Production):**
218
+ - Install `@lobu/worker` npm package
219
+ - Use your own base image
220
+ - Perfect for enterprise, compliance
221
+
222
+ ## Published Artifacts
223
+
224
+ **Docker Hub:**
225
+ ```bash
226
+ # For production (gateway)
227
+ docker pull buremba/lobu-gateway:0.1.0
228
+
229
+ # For quick start (extend this)
230
+ docker pull buremba/lobu-worker-base:0.1.0
231
+ ```
232
+
233
+ **NPM Registry:**
234
+ ```bash
235
+ # CLI tool
236
+ npm install -g create-lobu@0.1.0
237
+
238
+ # Worker runtime (for custom base images)
239
+ npm install -g @lobu/worker@0.1.0
240
+ ```
241
+
242
+ ## Architecture
243
+
244
+ ```
245
+ User creates project
246
+
247
+ mkdir my-bot && cd my-bot
248
+
249
+ npm create lobu
250
+
251
+ Choose: Base image or Package?
252
+
253
+ ┌───────────────┴────────────────┐
254
+ │ Base Image Mode │ Package Mode
255
+ │ │
256
+ │ FROM lobu-worker-base │ FROM your-company/base
257
+ │ RUN pip install pandas │ RUN npm install -g @lobu/worker
258
+ │ │ RUN pip install pandas
259
+ └───────────────┬────────────────┘
260
+
261
+ CLI generates docker-compose.yml
262
+
263
+ User runs: docker compose up -d
264
+
265
+ Docker builds worker:latest
266
+
267
+ Gateway spawns workers dynamically
268
+ ```
269
+
270
+ ## Contributing
271
+
272
+ Lobu CLI generates Docker Compose configurations. To modify the generated setup, see `src/commands/init.ts`.
273
+
274
+ ## License
275
+
276
+ MIT
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { runCli } from "../dist/index.js";
4
+
5
+ await runCli(process.argv);
package/bin/lobu.js ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { runCli } from "../dist/index.js";
4
+
5
+ await runCli(process.argv);
@@ -0,0 +1,11 @@
1
+ export interface ApiResponse<T = unknown> {
2
+ ok: boolean;
3
+ data?: T;
4
+ error?: string;
5
+ }
6
+ /**
7
+ * HTTP client for community.lobu.ai API.
8
+ * Stub for Phase 1 — most endpoints don't exist yet.
9
+ */
10
+ export declare function apiRequest<T = unknown>(path: string, options?: RequestInit): Promise<ApiResponse<T>>;
11
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,OAAO;IACtC,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAAC,CAAC,GAAG,OAAO,EAC1C,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAyBzB"}
@@ -0,0 +1,35 @@
1
+ import { getToken } from "./credentials.js";
2
+ const DEFAULT_API_URL = "https://community.lobu.ai/api/v1";
3
+ function getApiUrl() {
4
+ return process.env.LOBU_API_URL ?? DEFAULT_API_URL;
5
+ }
6
+ /**
7
+ * HTTP client for community.lobu.ai API.
8
+ * Stub for Phase 1 — most endpoints don't exist yet.
9
+ */
10
+ export async function apiRequest(path, options = {}) {
11
+ const token = await getToken();
12
+ const url = `${getApiUrl()}${path}`;
13
+ const headers = {
14
+ "Content-Type": "application/json",
15
+ "X-Lobu-Org": "default",
16
+ ...(token ? { Authorization: `Bearer ${token}` } : {}),
17
+ ...options.headers,
18
+ };
19
+ try {
20
+ const response = await fetch(url, { ...options, headers });
21
+ if (!response.ok) {
22
+ const body = await response.text();
23
+ return { ok: false, error: `${response.status}: ${body}` };
24
+ }
25
+ const data = (await response.json());
26
+ return { ok: true, data };
27
+ }
28
+ catch (err) {
29
+ return {
30
+ ok: false,
31
+ error: err instanceof Error ? err.message : String(err),
32
+ };
33
+ }
34
+ }
35
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,MAAM,eAAe,GAAG,kCAAkC,CAAC;AAE3D,SAAS,SAAS;IAChB,OAAO,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,eAAe,CAAC;AACrD,CAAC;AAQD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,IAAY,EACZ,UAAuB,EAAE;IAEzB,MAAM,KAAK,GAAG,MAAM,QAAQ,EAAE,CAAC;IAC/B,MAAM,GAAG,GAAG,GAAG,SAAS,EAAE,GAAG,IAAI,EAAE,CAAC;IAEpC,MAAM,OAAO,GAA2B;QACtC,cAAc,EAAE,kBAAkB;QAClC,YAAY,EAAE,SAAS;QACvB,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtD,GAAI,OAAO,CAAC,OAA8C;KAC3D,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;QAC3D,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,QAAQ,CAAC,MAAM,KAAK,IAAI,EAAE,EAAE,CAAC;QAC7D,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAM,CAAC;QAC1C,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC5B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;SACxD,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,13 @@
1
+ export interface Credentials {
2
+ token: string;
3
+ email?: string;
4
+ agentId?: string;
5
+ }
6
+ export declare function loadCredentials(): Promise<Credentials | null>;
7
+ export declare function saveCredentials(creds: Credentials): Promise<void>;
8
+ export declare function clearCredentials(): Promise<void>;
9
+ /**
10
+ * Get token from env var (CI/CD) or stored credentials.
11
+ */
12
+ export declare function getToken(): Promise<string | null>;
13
+ //# sourceMappingURL=credentials.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../src/api/credentials.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAOnE;AAED,wBAAsB,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAKvE;AAED,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAMtD;AAED;;GAEG;AACH,wBAAsB,QAAQ,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAMvD"}
@@ -0,0 +1,39 @@
1
+ import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
2
+ import { homedir } from "node:os";
3
+ import { join } from "node:path";
4
+ const CONFIG_DIR = join(homedir(), ".config", "lobu");
5
+ const CREDENTIALS_FILE = join(CONFIG_DIR, "credentials.json");
6
+ export async function loadCredentials() {
7
+ try {
8
+ const raw = await readFile(CREDENTIALS_FILE, "utf-8");
9
+ return JSON.parse(raw);
10
+ }
11
+ catch {
12
+ return null;
13
+ }
14
+ }
15
+ export async function saveCredentials(creds) {
16
+ await mkdir(CONFIG_DIR, { recursive: true });
17
+ await writeFile(CREDENTIALS_FILE, JSON.stringify(creds, null, 2), {
18
+ mode: 0o600,
19
+ });
20
+ }
21
+ export async function clearCredentials() {
22
+ try {
23
+ await rm(CREDENTIALS_FILE);
24
+ }
25
+ catch {
26
+ // File doesn't exist, nothing to clear
27
+ }
28
+ }
29
+ /**
30
+ * Get token from env var (CI/CD) or stored credentials.
31
+ */
32
+ export async function getToken() {
33
+ const envToken = process.env.LOBU_API_TOKEN;
34
+ if (envToken)
35
+ return envToken;
36
+ const creds = await loadCredentials();
37
+ return creds?.token ?? null;
38
+ }
39
+ //# sourceMappingURL=credentials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/api/credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;AACtD,MAAM,gBAAgB,GAAG,IAAI,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;AAQ9D,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;QACtD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAgB,CAAC;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,KAAkB;IACtD,MAAM,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,MAAM,SAAS,CAAC,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;QAChE,IAAI,EAAE,KAAK;KACZ,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,gBAAgB,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,uCAAuC;IACzC,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ;IAC5B,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IAC5C,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAE9B,MAAM,KAAK,GAAG,MAAM,eAAe,EAAE,CAAC;IACtC,OAAO,KAAK,EAAE,KAAK,IAAI,IAAI,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * `lobu dev` — smart wrapper around `docker compose up`.
3
+ * Reads lobu.toml, seeds .env + MCP config, then passes all args through.
4
+ *
5
+ * Examples:
6
+ * lobu dev → docker compose up
7
+ * lobu dev -d → docker compose up -d
8
+ * lobu dev --build → docker compose up --build
9
+ * lobu dev -d --build → docker compose up -d --build
10
+ * lobu dev --force-recreate → docker compose up --force-recreate
11
+ */
12
+ export declare function devCommand(cwd: string, passthroughArgs: string[]): Promise<void>;
13
+ //# sourceMappingURL=dev.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;GAUG;AACH,wBAAsB,UAAU,CAC9B,GAAG,EAAE,MAAM,EACX,eAAe,EAAE,MAAM,EAAE,GACxB,OAAO,CAAC,IAAI,CAAC,CA4Ff"}
@@ -0,0 +1,128 @@
1
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { spawn } from "node:child_process";
4
+ import chalk from "chalk";
5
+ import ora from "ora";
6
+ import { isLoadError, loadConfig } from "../config/loader.js";
7
+ import { transformConfig } from "../config/transformer.js";
8
+ /**
9
+ * `lobu dev` — smart wrapper around `docker compose up`.
10
+ * Reads lobu.toml, seeds .env + MCP config, then passes all args through.
11
+ *
12
+ * Examples:
13
+ * lobu dev → docker compose up
14
+ * lobu dev -d → docker compose up -d
15
+ * lobu dev --build → docker compose up --build
16
+ * lobu dev -d --build → docker compose up -d --build
17
+ * lobu dev --force-recreate → docker compose up --force-recreate
18
+ */
19
+ export async function devCommand(cwd, passthroughArgs) {
20
+ const result = await loadConfig(cwd);
21
+ if (isLoadError(result)) {
22
+ console.error(chalk.red(`\n ${result.error}`));
23
+ if (result.details) {
24
+ for (const detail of result.details) {
25
+ console.error(chalk.dim(` ${detail}`));
26
+ }
27
+ }
28
+ console.log();
29
+ process.exit(1);
30
+ }
31
+ const { config } = result;
32
+ const spinner = ora("Preparing local dev environment...").start();
33
+ try {
34
+ const { envVars, mcpConfig } = transformConfig(config);
35
+ // Write .env from lobu.toml-derived vars (merge with existing .env to preserve secrets)
36
+ const envPath = join(cwd, ".env");
37
+ let existingEnv = "";
38
+ try {
39
+ existingEnv = await readFile(envPath, "utf-8");
40
+ }
41
+ catch {
42
+ // No existing .env, start fresh
43
+ }
44
+ const existingVars = parseEnvFile(existingEnv);
45
+ // Existing vars take precedence — user's .env secrets aren't overwritten
46
+ const mergedVars = { ...envVars, ...existingVars };
47
+ const envContent = Object.entries(mergedVars)
48
+ .map(([k, v]) => `${k}=${v}`)
49
+ .join("\n");
50
+ await writeFile(envPath, envContent + "\n");
51
+ // Write MCP config if needed
52
+ if (mcpConfig) {
53
+ const lobuDir = join(cwd, ".lobu");
54
+ await mkdir(lobuDir, { recursive: true });
55
+ await writeFile(join(lobuDir, "mcp.config.json"), JSON.stringify({ mcpServers: mcpConfig }, null, 2));
56
+ }
57
+ // Load IDENTITY.md, SOUL.md, USER.md if they exist
58
+ await seedMarkdownFiles(cwd, mergedVars);
59
+ spinner.succeed("Environment prepared from lobu.toml");
60
+ // Check for docker-compose.yml
61
+ const composePath = join(cwd, "docker-compose.yml");
62
+ try {
63
+ await readFile(composePath, "utf-8");
64
+ }
65
+ catch {
66
+ console.log(chalk.yellow("\n No docker-compose.yml found. Run `lobu init` to generate one.\n"));
67
+ process.exit(1);
68
+ }
69
+ // Pass everything through to docker compose up
70
+ console.log(chalk.cyan(`\n Starting ${config.agent.name}...\n`));
71
+ const composeArgs = ["compose", "up", ...passthroughArgs];
72
+ const child = spawn("docker", composeArgs, {
73
+ cwd,
74
+ stdio: "inherit",
75
+ });
76
+ child.on("error", (err) => {
77
+ console.error(chalk.red(`\n Failed to start docker compose: ${err.message}`));
78
+ console.log(chalk.dim(" Make sure Docker Desktop is running.\n"));
79
+ process.exit(1);
80
+ });
81
+ child.on("exit", (code) => {
82
+ process.exit(code ?? 0);
83
+ });
84
+ }
85
+ catch (err) {
86
+ spinner.fail("Failed to prepare environment");
87
+ console.error(chalk.red(` ${err instanceof Error ? err.message : String(err)}`));
88
+ process.exit(1);
89
+ }
90
+ }
91
+ /**
92
+ * Read IDENTITY.md, SOUL.md, USER.md and add their content as env vars
93
+ * so the gateway can seed agent settings on startup.
94
+ */
95
+ async function seedMarkdownFiles(cwd, envVars) {
96
+ const files = [
97
+ { path: "IDENTITY.md", envKey: "AGENT_IDENTITY_MD" },
98
+ { path: "SOUL.md", envKey: "AGENT_SOUL_MD" },
99
+ { path: "USER.md", envKey: "AGENT_USER_MD" },
100
+ ];
101
+ for (const { path, envKey } of files) {
102
+ try {
103
+ const content = await readFile(join(cwd, path), "utf-8");
104
+ if (content.trim()) {
105
+ envVars[envKey] = content.trim();
106
+ }
107
+ }
108
+ catch {
109
+ // File doesn't exist, skip
110
+ }
111
+ }
112
+ }
113
+ function parseEnvFile(content) {
114
+ const vars = {};
115
+ for (const line of content.split("\n")) {
116
+ const trimmed = line.trim();
117
+ if (!trimmed || trimmed.startsWith("#"))
118
+ continue;
119
+ const eqIdx = trimmed.indexOf("=");
120
+ if (eqIdx === -1)
121
+ continue;
122
+ const key = trimmed.slice(0, eqIdx);
123
+ const value = trimmed.slice(eqIdx + 1);
124
+ vars[key] = value;
125
+ }
126
+ return vars;
127
+ }
128
+ //# sourceMappingURL=dev.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function initCommand(cwd?: string, projectNameArg?: string): Promise<void>;
2
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAgHA,wBAAsB,WAAW,CAC/B,GAAG,GAAE,MAAsB,EAC3B,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,IAAI,CAAC,CA+wBf"}