organtic 1.0.0 → 1.1.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 (2) hide show
  1. package/index.mjs +90 -130
  2. package/package.json +1 -1
package/index.mjs CHANGED
@@ -1,6 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { execSync } from "child_process";
3
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
4
+ import { join } from "path";
5
+ import { homedir } from "os";
4
6
  import { createInterface } from "readline";
5
7
 
6
8
  const MARKETPLACE_REPO = "Adanmohh/organtic";
@@ -53,7 +55,7 @@ const PLUGINS = [
53
55
  name: "pipeline",
54
56
  desc: "Pipeline orchestrator",
55
57
  experts: null,
56
- agents: "Chains 15 strategy experts across validate > build > launch",
58
+ agents: "Chains 15 explore experts across validate > build > launch",
57
59
  },
58
60
  ];
59
61
 
@@ -144,44 +146,54 @@ function box(chalk, lines, { title = "", width = 48, borderColor = null } = {})
144
146
  return out.join("\n");
145
147
  }
146
148
 
147
- function divider(chalk, { title = "", width = 48, borderColor = null } = {}) {
148
- const bc = borderColor || ((s) => gradientLine(chalk, s, width + 2));
149
- const vert = bc("\u2502");
150
- const leftT = bc("\u251c");
151
- const rightT = bc("\u2524");
152
- const horiz = (len) => bc("\u2500".repeat(len));
153
-
154
- if (title) {
155
- const titleStr = ` ${title} `;
156
- const remaining = width - titleStr.length;
157
- return ` ${leftT}${horiz(1)}${bc(titleStr)}${horiz(remaining - 1)}${rightT}`;
158
- }
159
- return ` ${leftT}${horiz(width)}${rightT}`;
160
- }
161
-
162
149
  // ---------------------------------------------------------------------------
163
- // CLI helpers
150
+ // Settings.json management
164
151
  // ---------------------------------------------------------------------------
165
152
 
166
- const rl = createInterface({ input: process.stdin, output: process.stdout });
167
- const ask = (q) => new Promise((r) => rl.question(q, r));
153
+ function getSettingsPath() {
154
+ return join(homedir(), ".claude", "settings.json");
155
+ }
168
156
 
169
- function runSilent(cmd) {
157
+ function readSettings() {
158
+ const path = getSettingsPath();
159
+ if (!existsSync(path)) return {};
170
160
  try {
171
- execSync(cmd, { stdio: "pipe" });
172
- return true;
161
+ return JSON.parse(readFileSync(path, "utf-8"));
173
162
  } catch {
174
- return false;
163
+ return {};
175
164
  }
176
165
  }
177
166
 
178
- function runVisible(cmd) {
179
- try {
180
- execSync(cmd, { stdio: "inherit" });
181
- return true;
182
- } catch {
183
- return false;
167
+ function writeSettings(settings) {
168
+ const dir = join(homedir(), ".claude");
169
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
170
+ writeFileSync(getSettingsPath(), JSON.stringify(settings, null, 2) + "\n");
171
+ }
172
+
173
+ function installPlugins(selected) {
174
+ const settings = readSettings();
175
+
176
+ // Add marketplace
177
+ if (!settings.extraKnownMarketplaces) {
178
+ settings.extraKnownMarketplaces = {};
179
+ }
180
+ settings.extraKnownMarketplaces[MARKETPLACE_NAME] = {
181
+ source: {
182
+ source: "github",
183
+ repo: MARKETPLACE_REPO,
184
+ },
185
+ };
186
+
187
+ // Enable selected plugins
188
+ if (!settings.enabledPlugins) {
189
+ settings.enabledPlugins = {};
190
+ }
191
+ for (const plugin of selected) {
192
+ settings.enabledPlugins[`${plugin.name}@${MARKETPLACE_NAME}`] = true;
184
193
  }
194
+
195
+ writeSettings(settings);
196
+ return true;
185
197
  }
186
198
 
187
199
  // ---------------------------------------------------------------------------
@@ -193,12 +205,10 @@ async function main() {
193
205
  const { default: ora } = await import("ora");
194
206
 
195
207
  const W = 48;
196
- const g = (s) => gradientLine(chalk, s, W + 2);
197
208
  const dim = chalk.dim;
198
209
  const bold = chalk.bold.white;
199
210
  const green = chalk.rgb(16, 185, 129);
200
211
  const cyan = chalk.rgb(6, 182, 212);
201
- const blue = chalk.rgb(59, 130, 246);
202
212
  const red = chalk.rgb(239, 68, 68);
203
213
 
204
214
  // ── Banner ──────────────────────────────────────────────────────────────
@@ -220,56 +230,28 @@ async function main() {
220
230
  console.log(banner);
221
231
  console.log();
222
232
 
223
- // ── Check Claude CLI ────────────────────────────────────────────────────
224
-
225
- const cliSpinner = ora({
226
- text: "Checking Claude Code CLI...",
227
- color: "cyan",
228
- }).start();
229
-
230
- try {
231
- execSync("claude --version", { stdio: "pipe" });
232
- cliSpinner.succeed(chalk.dim("Claude Code CLI found"));
233
- } catch {
234
- cliSpinner.fail(red("Claude Code CLI not found"));
235
- console.log();
236
- console.log(` ${dim("Install it first:")}`);
237
- console.log(` ${bold("npm install -g @anthropic-ai/claude-code")}`);
238
- console.log();
239
- process.exit(1);
240
- }
241
-
242
233
  // ── Pipeline Map ────────────────────────────────────────────────────────
243
234
 
244
- const vert = g("\u2502");
245
-
246
- const mapLines = [];
247
-
248
- // Top: Strategy Pipeline
249
- mapLines.push(box(chalk, [
235
+ console.log(box(chalk, [
250
236
  "",
251
237
  ` ${bold("validate")} ${dim("\u2500\u2500\u25b6")} ${bold("build")} ${dim("\u2500\u2500\u25b6")} ${bold("launch")}`,
252
238
  ` ${dim("3 experts")} ${dim("5 experts")} ${dim("7 experts")}`,
253
239
  "",
254
- ], { title: "Strategy Pipeline", width: W }));
240
+ ], { title: "Explore", width: W }));
255
241
 
256
- // Divider line for Execution (we'll build a second box)
257
- const execBox = [];
258
- execBox.push("");
259
- execBox.push(` ${bold("craft")} ${bold("document")} ${bold("present")} ${bold("studio")}`);
260
- execBox.push(` ${dim("4 agents")} ${dim("2 agents")} ${dim("1 agent")} ${dim("3 agents")}`);
261
- execBox.push("");
262
-
263
- mapLines.push(box(chalk, execBox, { title: "Execution", width: W }));
242
+ console.log(box(chalk, [
243
+ "",
244
+ ` ${bold("craft")} ${bold("document")} ${bold("present")} ${bold("studio")}`,
245
+ ` ${dim("4 agents")} ${dim("2 agents")} ${dim("1 agent")} ${dim("3 agents")}`,
246
+ "",
247
+ ], { title: "Exploit", width: W }));
264
248
 
265
- // Orchestration
266
- mapLines.push(box(chalk, [
249
+ console.log(box(chalk, [
267
250
  "",
268
- ` ${bold("pipeline")} ${dim("\u2014 chains all 15 strategy experts")}`,
251
+ ` ${bold("pipeline")} ${dim("\u2014 chains all 15 explore experts")}`,
269
252
  "",
270
253
  ], { title: "Orchestration", width: W }));
271
254
 
272
- console.log(mapLines.join("\n"));
273
255
  console.log();
274
256
 
275
257
  // ── Selection Menu ──────────────────────────────────────────────────────
@@ -277,41 +259,39 @@ async function main() {
277
259
  console.log(` ${gradientText(chalk, "Select plugins to install:")}`);
278
260
  console.log();
279
261
 
280
- console.log(` ${dim("Strategy Pipeline:")}`);
262
+ console.log(` ${dim("Explore:")}`);
281
263
  PLUGINS.slice(0, 3).forEach((p, i) => {
282
- const num = cyan(`[${i + 1}]`);
283
- const name = bold(p.name);
284
- const experts = dim(`${p.experts} experts \u2014 ${p.agents}`);
285
- console.log(` ${num} ${name} ${experts}`);
264
+ console.log(` ${cyan(`[${i + 1}]`)} ${bold(p.name)} ${dim(`${p.experts} experts \u2014 ${p.agents}`)}`);
286
265
  });
287
266
 
288
267
  console.log();
289
- console.log(` ${dim("Execution:")}`);
268
+ console.log(` ${dim("Exploit:")}`);
290
269
  PLUGINS.slice(3, 7).forEach((p, i) => {
291
- const num = cyan(`[${i + 4}]`);
292
- const name = bold(p.name);
293
- const experts = dim(`${p.experts} agent${p.experts > 1 ? "s" : ""} \u2014 ${p.agents}`);
294
- console.log(` ${num} ${name} ${experts}`);
270
+ console.log(` ${cyan(`[${i + 4}]`)} ${bold(p.name)} ${dim(`${p.experts} agent${p.experts > 1 ? "s" : ""} \u2014 ${p.agents}`)}`);
295
271
  });
296
272
 
297
273
  console.log();
298
274
  console.log(` ${dim("Orchestration:")}`);
299
- const pNum = cyan("[8]");
300
- console.log(` ${pNum} ${bold("pipeline")} ${dim(PLUGINS[7].agents)}`);
275
+ console.log(` ${cyan("[8]")} ${bold("pipeline")} ${dim(PLUGINS[7].agents)}`);
301
276
 
302
277
  console.log();
303
278
  console.log(` ${green("[A]")} ${bold("All plugins")} ${dim("(recommended)")}`);
304
- console.log(` ${green("[S]")} ${bold("Strategy only")} ${dim("(validate + build + launch + pipeline)")}`);
279
+ console.log(` ${green("[E]")} ${bold("Explore only")} ${dim("(validate + build + launch + pipeline)")}`);
305
280
  console.log();
306
281
 
307
- const choice = await ask(` ${cyan("\u276f")} ${dim("Your choice (1-8, A, S, comma-separated):")} `);
282
+ // ── User Selection ────────────────────────────────────────────────────
283
+
284
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
285
+ const choice = await new Promise((resolve) => {
286
+ rl.question(` ${cyan("\u276f")} Your choice (1-8, A, E, comma-separated): `, resolve);
287
+ });
308
288
  rl.close();
309
289
 
310
290
  let selected;
311
291
  const c = choice.trim().toLowerCase();
312
292
  if (c === "a" || c === "") {
313
293
  selected = PLUGINS;
314
- } else if (c === "s") {
294
+ } else if (c === "e") {
315
295
  selected = PLUGINS.filter((p) =>
316
296
  ["validate", "build", "launch", "pipeline"].includes(p.name)
317
297
  );
@@ -324,81 +304,61 @@ async function main() {
324
304
  }
325
305
 
326
306
  if (selected.length === 0) {
327
- console.log();
328
- console.log(` ${dim("No plugins selected. Exiting.")}`);
307
+ console.log(`\n ${dim("No plugins selected. Exiting.")}`);
329
308
  process.exit(0);
330
309
  }
331
310
 
332
- console.log();
333
- console.log(` ${gradientText(chalk, `Installing ${selected.length} plugin${selected.length > 1 ? "s" : ""}...`)}`);
334
311
  console.log();
335
312
 
336
- // ── Add Marketplace ─────────────────────────────────────────────────────
313
+ // ── Install ───────────────────────────────────────────────────────────
337
314
 
338
- const mpSpinner = ora({
339
- text: "Adding Organtic marketplace...",
315
+ const spinner = ora({
316
+ text: `Installing ${selected.length} plugin${selected.length > 1 ? "s" : ""} to ~/.claude/settings.json...`,
340
317
  color: "cyan",
341
318
  }).start();
342
319
 
343
- if (runSilent(`claude plugin marketplace add ${MARKETPLACE_REPO}`)) {
344
- mpSpinner.succeed(dim("Marketplace added"));
345
- } else {
346
- mpSpinner.warn(chalk.yellow("Marketplace may already be added"));
320
+ try {
321
+ installPlugins(selected);
322
+ spinner.succeed(
323
+ `${bold(`${selected.length} plugins`)} ${dim("installed to")} ${dim("~/.claude/settings.json")}`
324
+ );
325
+ } catch (err) {
326
+ spinner.fail(red(`Failed: ${err.message}`));
327
+ console.log();
328
+ console.log(` ${dim("Try manual install — add to ~/.claude/settings.json:")}`);
329
+ console.log(` ${dim(`"extraKnownMarketplaces": { "${MARKETPLACE_NAME}": { "source": { "source": "github", "repo": "${MARKETPLACE_REPO}" } } }`)}`);
330
+ process.exit(1);
347
331
  }
348
332
 
349
333
  console.log();
350
334
 
351
- // ── Install Plugins ─────────────────────────────────────────────────────
352
-
353
- let installed = 0;
354
- let failed = 0;
335
+ // ── Installed Plugins List ────────────────────────────────────────────
355
336
 
356
337
  for (const plugin of selected) {
357
- const spinner = ora({
358
- text: `Installing ${bold(plugin.name)}...`,
359
- color: "cyan",
360
- }).start();
361
-
362
- const ok = runSilent(`claude plugin install ${plugin.name}@${MARKETPLACE_NAME}`);
363
-
364
- if (ok) {
365
- installed++;
366
- spinner.succeed(`${bold(plugin.name)} ${dim("installed")}`);
367
- } else {
368
- failed++;
369
- spinner.fail(`${red(plugin.name)} ${dim("failed \u2014")} ${dim(`claude plugin install ${plugin.name}@${MARKETPLACE_NAME}`)}`);
370
- }
371
- }
372
-
373
- console.log();
374
-
375
- // ── Result Summary ──────────────────────────────────────────────────────
376
-
377
- if (failed === 0) {
378
- console.log(` ${green("\u2714")} ${bold(`${installed}/${selected.length} plugins installed successfully`)}`);
379
- } else {
380
- console.log(` ${green("\u2714")} ${installed} installed ${red("\u2718")} ${failed} failed`);
338
+ const label = plugin.experts
339
+ ? `${plugin.experts} expert${plugin.experts > 1 ? "s" : ""}`
340
+ : "orchestrator";
341
+ console.log(` ${green("\u2713")} ${bold(plugin.name)} ${dim(`\u2014 ${label}`)}`);
381
342
  }
382
343
 
383
344
  console.log();
384
345
 
385
- // ── Getting Started Card ────────────────────────────────────────────────
346
+ // ── Getting Started Card ──────────────────────────────────────────────
386
347
 
387
348
  const cyanBorder = (s) => cyan(s);
388
349
 
389
- const startCard = box(chalk, [
350
+ console.log(box(chalk, [
390
351
  "",
391
352
  ` ${dim("Start Claude Code:")} ${bold("claude")}`,
392
353
  ` ${dim("Run full pipeline:")} ${bold("/pipeline:run")} ${dim("Idea")}`,
393
354
  ` ${dim("Autonomous mode:")} ${bold("--autonomous")}`,
394
355
  ` ${dim("Single expert:")} ${bold("/value-mapper")} ${dim("Idea")}`,
395
356
  "",
396
- ` ${dim("Optional:")} ${bold("claude plugin install claude-mem")}`,
397
- ` ${dim("(enables cross-session memory)")}`,
357
+ ` ${dim("Cross-session memory:")}`,
358
+ ` ${bold("/plugin install claude-mem@thedotmack")}`,
398
359
  "",
399
- ], { title: "Getting Started", width: W, borderColor: cyanBorder });
360
+ ], { title: "Getting Started", width: W, borderColor: cyanBorder }));
400
361
 
401
- console.log(startCard);
402
362
  console.log();
403
363
  }
404
364
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "organtic",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "The AI-native organization. 25 experts from idea to launch. Strategy pipeline (validate > build > launch) + execution plugins (craft, document, present, studio). Claude Code plugin ecosystem.",
5
5
  "bin": {
6
6
  "organtic": "./index.mjs"