@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 +9 -0
- package/bin/ctx.js +77 -52
- package/package.json +1 -1
- package/plugins/ctx/lib/measure.js +4 -2
- package/plugins/ctx/lib/passthrough.js +2 -1
- package/plugins/ctx/lib/ruler-sync.js +1 -1
- package/plugins/ctx/lib/setup-wizard.js +1 -3
- package/plugins/ctx/lib/skillshare-sync.js +1 -1
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
|
|
45
|
-
ctx install --agent
|
|
46
|
-
ctx install --
|
|
47
|
-
ctx
|
|
48
|
-
ctx
|
|
49
|
-
ctx
|
|
50
|
-
ctx
|
|
51
|
-
ctx setup
|
|
52
|
-
ctx setup --
|
|
53
|
-
ctx
|
|
54
|
-
ctx
|
|
55
|
-
ctx
|
|
56
|
-
ctx
|
|
57
|
-
ctx
|
|
58
|
-
ctx
|
|
59
|
-
ctx
|
|
60
|
-
ctx
|
|
61
|
-
ctx
|
|
62
|
-
ctx sync --
|
|
63
|
-
ctx sync --
|
|
64
|
-
ctx sync --
|
|
65
|
-
ctx sync --
|
|
66
|
-
ctx sync --skills
|
|
67
|
-
ctx sync --
|
|
68
|
-
ctx sync --workflows
|
|
69
|
-
ctx sync --workflows --
|
|
70
|
-
ctx sync --
|
|
71
|
-
ctx
|
|
72
|
-
ctx
|
|
73
|
-
ctx
|
|
74
|
-
ctx
|
|
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,
|
|
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(
|
|
546
|
-
await install({ agent,
|
|
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("
|
|
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("
|
|
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("
|
|
576
|
-
console.log("│
|
|
577
|
-
console.log("│
|
|
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
|
-
|
|
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
|
-
|
|
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
|
@@ -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 {
|
|
@@ -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:
|
|
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
|
|