@minhpnq1807/contextos 0.5.26 → 0.5.28

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.28
4
+
5
+ - **Consistent `◇`/`│` UI formatting for all install and setup output:** All progress bars, detail lines, and status messages from `ctx install` and `ctx setup` are now captured and re-emitted with `◇` step headers and `│`-indented detail lines. Added `captureSetupOutput` helper that intercepts both `console.log` and `process.stderr.write` to ensure nothing leaks unprefixed.
6
+ - **Fix broken `syncSkills` call in setup:** Restored the missing `syncSkills()` invocation that was accidentally dropped during a previous edit.
7
+
8
+ ## 0.5.27
9
+
10
+ - **Fix Windows `spawnSync`/`execFileSync` ENOENT across all modules:** Added `shell: true` to every remaining child-process invocation in `ruler-sync.js`, `skillshare-sync.js`, `passthrough.js`, and `measure.js`. Without this, Windows cannot resolve `.cmd`/`.ps1` shims (e.g. `npm.cmd`, `ruler.cmd`, `skillshare.cmd`) via PATH, causing `ctx setup` to crash during the Ruler/Skillshare installation step.
11
+
3
12
  ## 0.5.26
4
13
 
5
14
  - **Interactive `ctx install`:** Running `ctx install` without `--agent` now shows an interactive multi-select prompt (↑/↓ to navigate, Space to toggle, Enter to confirm) letting you pick which agents to install in one go.
package/bin/ctx.js CHANGED
@@ -41,41 +41,37 @@ function usage() {
41
41
  return `ContextOS (ctx)
42
42
 
43
43
  Usage:
44
- ctx install (interactive agent selection)
45
- ctx install --agent codex (direct install for a specific agent)
46
- ctx install --agent claude
47
- ctx install --agent agy
48
- ctx install --quiet
49
- ctx install --inject
50
- ctx install --copy
51
- ctx setup
52
- ctx setup --yes
53
- ctx setup --agents codex,claude,agy
54
- ctx setup --no-rules
55
- ctx setup --no-skills
56
- ctx setup --quiet
57
- ctx debug -- "task"
58
- ctx report
59
- ctx evidence
60
- ctx stats
61
- ctx benchmark -- "task"
62
- ctx sync --rules
63
- ctx sync --rules --agents codex,claude,antigravity
64
- ctx sync --rules --dry-run
65
- ctx sync --rules --no-import-codex-mcp
66
- ctx sync --skills
67
- ctx sync --workflows
68
- ctx sync --workflows --agents codex,claude,agy
69
- ctx sync --workflows --dry-run
70
- ctx sync --skills --dry-run
71
- ctx sync --skills --no-collect
72
- ctx sync --skills --no-embeddings
73
- ctx sync --skills --verbose
74
- ctx sync --skills --agents codex,claude,antigravity
75
- ctx embeddings warm -- "task"
76
- ctx ruler -- <ruler args>
77
- ctx skillshare -- <skillshare args>
78
- ctx --version
44
+ ctx install Interactive multi-select agent installer
45
+ ctx install --agent <name> Install a specific agent (codex|claude|agy)
46
+ ctx install --copy Legacy: copy plugin folder only (no hooks/mcp)
47
+ ctx setup Interactive full setup wizard
48
+ ctx setup --yes Auto-confirm all setup prompts
49
+ ctx setup --agents codex,claude,agy Pre-select agents to install
50
+ ctx setup --no-rules Skip AGENTS.md rule sync
51
+ ctx setup --no-skills Skip skill sync
52
+ ctx setup --quiet Quiet mode (minimal output)
53
+ ctx debug -- "task" Debug a task with ContextOS tracing
54
+ ctx report Show last ContextOS compliance report
55
+ ctx evidence Show evidence from last report
56
+ ctx stats Show workspace statistics
57
+ ctx benchmark -- "task" Benchmark workspace for a task
58
+ ctx sync --rules Sync AGENTS.md rules to all agents
59
+ ctx sync --rules --agents codex,claude,agy Sync rules to specific agents only
60
+ ctx sync --rules --dry-run Preview rule sync without writing
61
+ ctx sync --rules --no-import-codex-mcp Skip importing Codex MCP servers
62
+ ctx sync --skills Sync skills across agents
63
+ ctx sync --skills --agents codex,claude,agy Sync skills to specific agents only
64
+ ctx sync --skills --dry-run Preview skill sync without writing
65
+ ctx sync --skills --no-collect Skip collecting new skills
66
+ ctx sync --skills --no-embeddings Skip embedding generation
67
+ ctx sync --skills --verbose Verbose skill sync output
68
+ ctx sync --workflows Sync workflows across agents
69
+ ctx sync --workflows --agents codex,claude,agy Sync workflows to specific agents
70
+ ctx sync --workflows --dry-run Preview workflow sync without writing
71
+ ctx embeddings warm -- "task" Pre-warm embedding caches for a task
72
+ ctx ruler -- <ruler args> Passthrough to ruler CLI
73
+ ctx skillshare -- <skillshare args> Passthrough to skillshare CLI
74
+ ctx --version Show installed version
79
75
  `;
80
76
  }
81
77
 
@@ -102,6 +98,29 @@ function normalizeInstallAgent(agent) {
102
98
  return normalized;
103
99
  }
104
100
 
101
+ /**
102
+ * Capture all console.log and process.stderr.write output from an async fn.
103
+ * Returns an array of clean text lines (no \r, no trailing whitespace).
104
+ */
105
+ async function captureSetupOutput(fn) {
106
+ const lines = [];
107
+ const origLog = console.log;
108
+ const origStderrWrite = process.stderr.write;
109
+ console.log = (...args) => lines.push(args.map(String).join(" "));
110
+ process.stderr.write = (chunk) => {
111
+ const text = String(chunk).replace(/\r/g, "").trim();
112
+ if (text) lines.push(text);
113
+ return true;
114
+ };
115
+ try {
116
+ await fn();
117
+ } finally {
118
+ console.log = origLog;
119
+ process.stderr.write = origStderrWrite;
120
+ }
121
+ return lines;
122
+ }
123
+
105
124
  function createInstallProgress({ quiet = false } = {}) {
106
125
  const enabled = !quiet && process.stderr.isTTY;
107
126
  const frames = ["-", "\\", "|", "/"];
@@ -183,7 +202,8 @@ function agentInstallRoot(agent) {
183
202
  return path.join(contextOSDataDir(), "agents", agent, "contextos");
184
203
  }
185
204
 
186
- async function install({ copy = false, inject = true, agent = "codex" } = {}) {
205
+ async function install({ copy = false, agent = "codex" } = {}) {
206
+ const inject = true; // Prompt injection is always enabled
187
207
  agent = normalizeInstallAgent(agent);
188
208
  if (copy) {
189
209
  copyInstall();
@@ -516,7 +536,6 @@ async function setup({ args = [], cwd = process.cwd() } = {}) {
516
536
  options.agents = selected;
517
537
  const rl2 = readline.createInterface({ input, output });
518
538
  try {
519
- options.inject = await askSetupYesNo(rl2, "Enable prompt context injection?", options.inject);
520
539
  options.syncRules = await askSetupYesNo(rl2, "Sync project rules and MCP servers through Ruler?", options.syncRules);
521
540
  options.syncSkills = await askSetupYesNo(rl2, "Sync skills through skillshare?", options.syncSkills);
522
541
  } finally {
@@ -525,7 +544,6 @@ async function setup({ args = [], cwd = process.cwd() } = {}) {
525
544
  } else {
526
545
  try {
527
546
  console.log(`◇ Install for agents:\n│ ${options.agents.join(", ")}`);
528
- options.inject = await askSetupYesNo(rl, "Enable prompt context injection?", options.inject);
529
547
  options.syncRules = await askSetupYesNo(rl, "Sync project rules and MCP servers through Ruler?", options.syncRules);
530
548
  options.syncSkills = await askSetupYesNo(rl, "Sync skills through skillshare?", options.syncSkills);
531
549
  } finally {
@@ -542,24 +560,26 @@ async function setup({ args = [], cwd = process.cwd() } = {}) {
542
560
  if (!options.agents.length) throw new Error("No agents selected. Use --agents codex,claude,agy.");
543
561
 
544
562
  for (const agent of options.agents) {
545
- console.log(`● Setting up ${agent}...`);
546
- await install({ agent, inject: options.inject, copy: false });
563
+ console.log(`◇ Setting up ${agent}...`);
564
+ const lines = await captureSetupOutput(() => install({ agent, copy: false }));
565
+ for (const line of lines) console.log(`│ ${line}`);
547
566
  }
548
567
 
549
568
  if (options.syncRules) {
550
- console.log(" Syncing project rules and MCP servers...");
569
+ console.log(" Syncing project rules and MCP servers...");
551
570
  const syncAgents = options.agents.map((agent) => agent === "agy" ? "antigravity" : agent).join(",");
552
571
  const syncArgs = ["--rules", "--agents", syncAgents];
553
572
  if (options.yes) syncArgs.push("--yes");
554
- await syncRules({ cwd, rootDir, args: syncArgs });
573
+ const lines = await captureSetupOutput(() => syncRules({ cwd, rootDir, args: syncArgs }));
574
+ for (const line of lines) console.log(`│ ${line}`);
555
575
  }
556
576
 
557
577
  if (options.syncSkills) {
558
- console.log(" Syncing skills...");
578
+ console.log(" Syncing skills...");
559
579
  const skillAgents = options.agents.map((agent) => agent === "agy" ? "antigravity" : agent).join(",");
560
580
  const syncArgs = ["--skills", "--agents", skillAgents];
561
581
  if (options.yes) syncArgs.push("--yes");
562
- await syncSkills({
582
+ const lines = await captureSetupOutput(() => syncSkills({
563
583
  cwd,
564
584
  args: syncArgs,
565
585
  rebuildSkillEmbeddings: async ({ cwd: skillCwd, sourceDir }) => warmSkillEmbeddings({
@@ -568,14 +588,15 @@ async function setup({ args = [], cwd = process.cwd() } = {}) {
568
588
  allowRemote: !isModelCacheReady(contextOSDataDir()),
569
589
  skills: scanSkills({ cwd: skillCwd, roots: [sourceDir] })
570
590
  })
571
- });
591
+ }));
592
+ for (const line of lines) console.log(`│ ${line}`);
572
593
  }
573
594
 
574
595
  console.log("");
575
- console.log("╭─ ContextOS is ready ───────────────────────────────────────╮");
576
- console.log("│ Next: restart/open your agent from this project directory.");
577
- console.log("│ Try: ctx debug -- \"Recheck authen flow\"");
578
- console.log("╰───────────────────────────────────────────────────────────╯");
596
+ console.log(" ContextOS is ready");
597
+ console.log("│ Next: restart/open your agent from this project directory.");
598
+ console.log("│ Try: ctx debug -- \"Recheck authen flow\"");
599
+ console.log("");
579
600
  }
580
601
 
581
602
  const args = process.argv.slice(2);
@@ -594,12 +615,14 @@ try {
594
615
  console.log(packageVersion());
595
616
  } else if (command === "install") {
596
617
  const copy = args.includes("--copy");
597
- const inject = args.includes("--inject") || !args.includes("--quiet");
598
618
  const explicitAgent = installAgentFromArgs(args);
599
619
 
600
620
  if (explicitAgent) {
601
621
  // Direct mode: ctx install --agent <name>
602
- await install({ copy, inject, agent: explicitAgent });
622
+ console.log(`◇ Installing ${explicitAgent}...`);
623
+ const lines = await captureSetupOutput(() => install({ copy, agent: explicitAgent }));
624
+ for (const line of lines) console.log(`│ ${line}`);
625
+ console.log("");
603
626
  } else {
604
627
  // Interactive mode: ctx install
605
628
  const selected = await multiSelect({
@@ -610,7 +633,9 @@ try {
610
633
  console.log("No agents selected. Nothing to install.");
611
634
  } else {
612
635
  for (const agent of selected) {
613
- await install({ copy, inject, agent });
636
+ console.log(`◇ Installing ${agent}...`);
637
+ const lines = await captureSetupOutput(() => install({ copy, agent }));
638
+ for (const line of lines) console.log(`│ ${line}`);
614
639
  console.log("");
615
640
  }
616
641
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@minhpnq1807/contextos",
3
- "version": "0.5.26",
3
+ "version": "0.5.28",
4
4
  "description": "Task-aware AGENTS.md context injection and compliance reporting for Codex, Claude Code, and Antigravity.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -53,7 +53,8 @@ export function readGitSnapshot({ cwd = process.cwd() } = {}) {
53
53
  cwd,
54
54
  encoding: "utf8",
55
55
  stdio: ["ignore", "pipe", "pipe"],
56
- timeout: 1000
56
+ timeout: 1000,
57
+ shell: true
57
58
  });
58
59
  return parseGitDiff(diff);
59
60
  } catch {
@@ -62,7 +63,8 @@ export function readGitSnapshot({ cwd = process.cwd() } = {}) {
62
63
  cwd,
63
64
  encoding: "utf8",
64
65
  stdio: ["ignore", "pipe", "pipe"],
65
- timeout: 1000
66
+ timeout: 1000,
67
+ shell: true
66
68
  });
67
69
  const changedFiles = parseStatusFiles(status);
68
70
  return {
@@ -33,7 +33,8 @@ export function runPassthrough({
33
33
  const result = spawn(command, args, {
34
34
  cwd,
35
35
  env,
36
- stdio: "inherit"
36
+ stdio: "inherit",
37
+ shell: true
37
38
  });
38
39
 
39
40
  if (result.error) {
@@ -24,7 +24,7 @@ function statusLine(label, value) {
24
24
 
25
25
  function runCommand(command, args, { cwd = process.cwd(), stdio = "pipe", dryRun = false } = {}) {
26
26
  if (dryRun) return { stdout: "", skipped: true };
27
- const stdout = execFileSync(command, args, { cwd, stdio, encoding: "utf8" });
27
+ const stdout = execFileSync(command, args, { cwd, stdio, encoding: "utf8", shell: true });
28
28
  return { stdout: stdout || "" };
29
29
  }
30
30
 
@@ -12,7 +12,6 @@ export function parseSetupArgs(args = []) {
12
12
  agentsProvided,
13
13
  yes: args.includes("--yes") || args.includes("-y"),
14
14
  quiet: args.includes("--quiet"),
15
- inject: !args.includes("--quiet") && !args.includes("--no-inject"),
16
15
  syncRules: !args.includes("--no-rules"),
17
16
  syncSkills: !args.includes("--no-skills")
18
17
  };
@@ -35,14 +34,13 @@ export function normalizeSetupAgent(agent) {
35
34
  export function setupSummaryLines({
36
35
  cwd = process.cwd(),
37
36
  agents = DEFAULT_AGENTS,
38
- inject = true,
39
37
  syncRules = true,
40
38
  syncSkills = true
41
39
  } = {}) {
42
40
  return [
43
41
  `Installation directory: ${cwd}`,
44
42
  `Agents: ${agents.join(", ") || "(none)"}`,
45
- `Prompt context injection: ${inject ? "enabled" : "quiet logging only"}`,
43
+ `Prompt context injection: always enabled`,
46
44
  `Ruler rule/MCP sync: ${syncRules ? "enabled" : "skipped"}`,
47
45
  `skillshare skill sync: ${syncSkills ? "enabled" : "skipped"}`
48
46
  ];
@@ -21,7 +21,7 @@ function statusLine(label, value) {
21
21
 
22
22
  function runCommand(command, args = [], { cwd = process.cwd(), stdio = "pipe", dryRun = false } = {}) {
23
23
  if (dryRun) return { stdout: "", skipped: true };
24
- const stdout = execFileSync(command, args, { cwd, stdio, encoding: "utf8" });
24
+ const stdout = execFileSync(command, args, { cwd, stdio, encoding: "utf8", shell: true });
25
25
  return { stdout: stdout || "" };
26
26
  }
27
27