@minhpnq1807/contextos 0.5.6 → 0.5.8
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 +11 -0
- package/README.md +40 -2
- package/bin/ctx.js +113 -0
- package/package.json +1 -1
- package/plugins/ctx/lib/passthrough.js +50 -0
- package/plugins/ctx/lib/setup-wizard.js +47 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.8
|
|
4
|
+
|
|
5
|
+
- Adds explicit `ctx setup` interactive onboarding for installing agents, enabling injection, syncing Ruler rules/MCP servers, and syncing skills through skillshare.
|
|
6
|
+
- Adds non-interactive setup flags: `--yes`, `--agents`, `--no-rules`, `--no-skills`, `--quiet`, and `--no-inject`.
|
|
7
|
+
- Keeps npm install lifecycle clean; setup only runs when the user explicitly invokes `ctx setup`.
|
|
8
|
+
|
|
9
|
+
## 0.5.7
|
|
10
|
+
|
|
11
|
+
- Adds thin passthrough commands `ctx ruler -- <args>` and `ctx skillshare -- <args>` for upstream admin/debug workflows without reimplementing those CLIs.
|
|
12
|
+
- Preserves upstream output and exit status for passthrough commands, with install hints when the upstream binary is missing.
|
|
13
|
+
|
|
3
14
|
## 0.5.6
|
|
4
15
|
|
|
5
16
|
- Adds visible `ctx install` progress from 0-100 so long model/file/skill embedding warmups no longer look stalled.
|
package/README.md
CHANGED
|
@@ -11,10 +11,25 @@ Published package: [`@minhpnq1807/contextos`](https://www.npmjs.com/package/@min
|
|
|
11
11
|
```bash
|
|
12
12
|
npm install -g @minhpnq1807/contextos
|
|
13
13
|
ctx --version
|
|
14
|
-
ctx
|
|
14
|
+
ctx setup
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
`ctx setup` is the recommended first-run flow. It asks which agents to configure, whether prompt context injection should be enabled, whether to sync project rules/MCP through Ruler, and whether to sync skills through skillshare. It only runs when you explicitly invoke it; npm install does not run setup automatically.
|
|
18
|
+
|
|
19
|
+
For scriptable installs, use:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
ctx setup --yes
|
|
23
|
+
ctx setup --yes --agents codex,claude,agy
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Restart your agent after setup, then use it normally. ContextOS runs through agent hooks and the `ctx-mcp` MCP server.
|
|
27
|
+
|
|
28
|
+
Codex-only install is still available:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
ctx install
|
|
32
|
+
```
|
|
18
33
|
|
|
19
34
|
Claude Code and Antigravity are supported through their native hook systems:
|
|
20
35
|
|
|
@@ -27,6 +42,7 @@ You can also run without a global install:
|
|
|
27
42
|
|
|
28
43
|
```bash
|
|
29
44
|
npx @minhpnq1807/contextos@latest install
|
|
45
|
+
npx @minhpnq1807/contextos@latest setup
|
|
30
46
|
npx @minhpnq1807/contextos@latest install claude
|
|
31
47
|
npx @minhpnq1807/contextos@latest install agy
|
|
32
48
|
```
|
|
@@ -269,6 +285,20 @@ ctx sync --rules --no-import-codex-mcp
|
|
|
269
285
|
|
|
270
286
|
`ctx sync --rules` is project-scoped. It writes `.ruler/ruler.toml` in the current project and lets Ruler generate agent files from that project source of truth. ContextOS runtime history still follows the project-path isolation model described below.
|
|
271
287
|
|
|
288
|
+
## Upstream Passthrough
|
|
289
|
+
|
|
290
|
+
ContextOS exposes thin passthrough commands for Ruler and skillshare admin/debug workflows:
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
ctx ruler -- apply --agents codex,claude,antigravity
|
|
294
|
+
ctx ruler -- init
|
|
295
|
+
ctx skillshare -- status
|
|
296
|
+
ctx skillshare -- target list
|
|
297
|
+
ctx skillshare -- doctor
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
Everything after `--` is forwarded unchanged to the upstream CLI. ContextOS does not reinterpret those args, and it preserves the upstream output and exit status. Use `ctx sync --rules` and `ctx sync --skills` for ContextOS-managed workflows; use passthrough when you need a native Ruler or skillshare command.
|
|
301
|
+
|
|
272
302
|
## Troubleshooting
|
|
273
303
|
|
|
274
304
|
### `ctx-mcp bridge socket not found`
|
|
@@ -309,6 +339,12 @@ This warning comes from a transitive dependency in the local embedding/WASM stac
|
|
|
309
339
|
| `ctx install --quiet` | Installs ContextOS in measurement-only mode. | You want reports and stats but do not want visible injected context. | Installs the same hooks, but prompt hooks return empty context. |
|
|
310
340
|
| `ctx install --inject` | Installs ContextOS with explicit injection mode. | You want to be explicit in scripts or docs. | Same runtime behavior as the default install mode; if combined with `--quiet`, `--inject` wins. |
|
|
311
341
|
| `ctx install --copy` | Copies only the plugin payload to `$CODEX_HOME/plugins/ctx`. | Local development or manual plugin experiments. | Does not register marketplace, MCP, or global hooks. |
|
|
342
|
+
| `ctx setup` | Runs the first-run setup wizard. | You want the recommended onboarding flow after `npm install -g @minhpnq1807/contextos`. | Installs selected agents, optionally syncs Ruler rules/MCP and skillshare skills, then prints next steps. |
|
|
343
|
+
| `ctx setup --yes` | Runs setup with defaults non-interactively. | You want scriptable all-agent setup. | Uses `codex,claude,agy`, enables injection, syncs rules, syncs skills, and passes `--yes` to dependency setup prompts. |
|
|
344
|
+
| `ctx setup --agents <list>` | Runs setup for selected agents. | You want only part of the default set. | Accepts comma-separated `codex`, `claude`, `agy`, or `antigravity`. |
|
|
345
|
+
| `ctx setup --no-rules` | Skips Ruler sync during setup. | You only want hooks/MCP install and maybe skill sync. | Does not run `ctx sync --rules`. |
|
|
346
|
+
| `ctx setup --no-skills` | Skips skillshare sync during setup. | You do not want shared skills configured. | Does not run `ctx sync --skills`. |
|
|
347
|
+
| `ctx setup --quiet` | Runs setup in measurement-only mode. | You want reports/stats without visible injected prompt context. | Installs hooks with prompt context injection disabled. |
|
|
312
348
|
| `ctx debug -- "task"` | Runs the scheduler locally for a fake prompt. | You want to see which AGENTS.md rules and files ContextOS would inject before using Codex. | Prints rule scores, scoring reasons, suggested files, and final `additionalContext`. |
|
|
313
349
|
| `ctx report` | Shows the last Stop-hook compliance report for the current workspace. | An agent task has finished and you want the summary again. | Reads `~/.ctx/contextos/workspaces/<workspace-id>/last-report.json`. |
|
|
314
350
|
| `ctx evidence` | Shows detailed evidence behind the last report for the current workspace. | You want to inspect why a rule was marked `followed`, `ignored`, or `unknown`. | Prints rule text, source file, score, status, and evidence reason. |
|
|
@@ -324,6 +360,8 @@ This warning comes from a transitive dependency in the local embedding/WASM stac
|
|
|
324
360
|
| `ctx sync --skills --dry-run` | Previews skillshare sync. | You want to inspect behavior before changing skill directories. | Runs `skillshare sync --dry-run` and skips embedding rebuild. |
|
|
325
361
|
| `ctx sync --skills --no-collect` | Skips collecting existing agent skills into skillshare. | You already manage `~/.config/skillshare/skills` and only want to push it out. | Initializes/syncs skillshare without running `skillshare backup` or `skillshare collect --all`. |
|
|
326
362
|
| `ctx embeddings warm -- "task"` | Prepares local semantic embedding caches. | First install, CI smoke checks, or after changing AGENTS.md/project files/skills. | Loads/downloads `Xenova/all-MiniLM-L6-v2` and writes rule, file-path, and skill vectors to `~/.ctx/contextos/embeddings.db`. |
|
|
363
|
+
| `ctx ruler -- <args>` | Forwards args to the installed `ruler` CLI. | You need native Ruler commands such as `init`, `apply`, or `revert`. | Preserves Ruler stdout/stderr and exit status. |
|
|
364
|
+
| `ctx skillshare -- <args>` | Forwards args to the installed `skillshare` CLI. | You need native skillshare commands such as `status`, `target list`, `doctor`, `push`, or `pull`. | Preserves skillshare stdout/stderr and exit status. |
|
|
327
365
|
| `ctx --version` | Prints the installed ContextOS CLI version. | You want to confirm which npm version is being executed. | Prints the version from package metadata. |
|
|
328
366
|
|
|
329
367
|
## Runtime Files
|
package/bin/ctx.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
|
+
import readline from "node:readline/promises";
|
|
5
|
+
import { stdin as input, stdout as output } from "node:process";
|
|
4
6
|
import { fileURLToPath } from "node:url";
|
|
5
7
|
import { execFileSync } from "node:child_process";
|
|
6
8
|
|
|
@@ -24,6 +26,8 @@ import { installAntigravityMcp } from "../plugins/ctx/lib/antigravity-mcp.js";
|
|
|
24
26
|
import { syncRules } from "../plugins/ctx/lib/ruler-sync.js";
|
|
25
27
|
import { syncSkills } from "../plugins/ctx/lib/skillshare-sync.js";
|
|
26
28
|
import { scanSkills, warmSkillEmbeddings } from "../plugins/ctx/lib/skill-discoverer.js";
|
|
29
|
+
import { parsePassthroughArgs, runPassthrough } from "../plugins/ctx/lib/passthrough.js";
|
|
30
|
+
import { parseAgentList, parseSetupArgs, setupSummaryLines } from "../plugins/ctx/lib/setup-wizard.js";
|
|
27
31
|
|
|
28
32
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
29
33
|
const rootDir = path.resolve(__dirname, "..");
|
|
@@ -41,6 +45,12 @@ Usage:
|
|
|
41
45
|
ctx install --quiet
|
|
42
46
|
ctx install --inject
|
|
43
47
|
ctx install --copy
|
|
48
|
+
ctx setup
|
|
49
|
+
ctx setup --yes
|
|
50
|
+
ctx setup --agents codex,claude,agy
|
|
51
|
+
ctx setup --no-rules
|
|
52
|
+
ctx setup --no-skills
|
|
53
|
+
ctx setup --quiet
|
|
44
54
|
ctx debug -- "task"
|
|
45
55
|
ctx report
|
|
46
56
|
ctx evidence
|
|
@@ -55,6 +65,8 @@ Usage:
|
|
|
55
65
|
ctx sync --skills --no-collect
|
|
56
66
|
ctx sync --skills --agents codex,claude,antigravity
|
|
57
67
|
ctx embeddings warm -- "task"
|
|
68
|
+
ctx ruler -- <ruler args>
|
|
69
|
+
ctx skillshare -- <skillshare args>
|
|
58
70
|
ctx --version
|
|
59
71
|
`;
|
|
60
72
|
}
|
|
@@ -391,6 +403,96 @@ async function warmEmbeddings(task) {
|
|
|
391
403
|
console.log(`Cache: ${result.cachePath}`);
|
|
392
404
|
}
|
|
393
405
|
|
|
406
|
+
function printSetupBanner() {
|
|
407
|
+
console.log("");
|
|
408
|
+
console.log("╭─ ContextOS setup ─────────────────────────────────────────╮");
|
|
409
|
+
console.log("│ Task-aware rules, MCP sync, and skill discovery for agents │");
|
|
410
|
+
console.log("╰───────────────────────────────────────────────────────────╯");
|
|
411
|
+
console.log("");
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
async function askSetupQuestion(rl, question, defaultValue) {
|
|
415
|
+
const suffix = defaultValue ? ` (${defaultValue})` : "";
|
|
416
|
+
const answer = await rl.question(`◇ ${question}${suffix}: `);
|
|
417
|
+
return answer.trim() || defaultValue;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
async function askSetupYesNo(rl, question, defaultValue = true) {
|
|
421
|
+
const suffix = defaultValue ? "Y/n" : "y/N";
|
|
422
|
+
const answer = await askSetupQuestion(rl, question, suffix);
|
|
423
|
+
if (!answer || answer === suffix) return defaultValue;
|
|
424
|
+
return !/^n(o)?$/i.test(answer.trim());
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
async function setup({ args = [], cwd = process.cwd() } = {}) {
|
|
428
|
+
const options = parseSetupArgs(args);
|
|
429
|
+
const interactive = !options.yes && process.stdin.isTTY;
|
|
430
|
+
|
|
431
|
+
printSetupBanner();
|
|
432
|
+
console.log(`◇ Installation directory:\n│ ${cwd}`);
|
|
433
|
+
|
|
434
|
+
if (interactive) {
|
|
435
|
+
const rl = readline.createInterface({ input, output });
|
|
436
|
+
try {
|
|
437
|
+
const proceed = await askSetupYesNo(rl, "Install to this directory?", true);
|
|
438
|
+
if (!proceed) {
|
|
439
|
+
console.log("Setup cancelled.");
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
const agents = await askSetupQuestion(rl, "Install for agents? comma-separated", options.agents.join(","));
|
|
443
|
+
options.agents = parseAgentList(agents);
|
|
444
|
+
options.inject = await askSetupYesNo(rl, "Enable prompt context injection?", options.inject);
|
|
445
|
+
options.syncRules = await askSetupYesNo(rl, "Sync project rules and MCP servers through Ruler?", options.syncRules);
|
|
446
|
+
options.syncSkills = await askSetupYesNo(rl, "Sync skills through skillshare?", options.syncSkills);
|
|
447
|
+
} finally {
|
|
448
|
+
rl.close();
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
console.log("");
|
|
453
|
+
console.log("◇ Ready to setup:");
|
|
454
|
+
for (const line of setupSummaryLines({ cwd, ...options })) console.log(`│ ${line}`);
|
|
455
|
+
console.log("");
|
|
456
|
+
|
|
457
|
+
if (!options.agents.length) throw new Error("No agents selected. Use --agents codex,claude,agy.");
|
|
458
|
+
|
|
459
|
+
for (const agent of options.agents) {
|
|
460
|
+
console.log(`● Setting up ${agent}...`);
|
|
461
|
+
await install({ agent, inject: options.inject, copy: false });
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
if (options.syncRules) {
|
|
465
|
+
console.log("● Syncing project rules and MCP servers...");
|
|
466
|
+
const syncAgents = options.agents.map((agent) => agent === "agy" ? "antigravity" : agent).join(",");
|
|
467
|
+
const syncArgs = ["--rules", "--agents", syncAgents];
|
|
468
|
+
if (options.yes) syncArgs.push("--yes");
|
|
469
|
+
await syncRules({ cwd, rootDir, args: syncArgs });
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
if (options.syncSkills) {
|
|
473
|
+
console.log("● Syncing skills...");
|
|
474
|
+
const skillAgents = options.agents.map((agent) => agent === "agy" ? "antigravity" : agent).join(",");
|
|
475
|
+
const syncArgs = ["--skills", "--agents", skillAgents];
|
|
476
|
+
if (options.yes) syncArgs.push("--yes");
|
|
477
|
+
await syncSkills({
|
|
478
|
+
cwd,
|
|
479
|
+
args: syncArgs,
|
|
480
|
+
rebuildSkillEmbeddings: async ({ cwd: skillCwd, sourceDir }) => warmSkillEmbeddings({
|
|
481
|
+
cwd: skillCwd,
|
|
482
|
+
dataDir: contextOSDataDir(),
|
|
483
|
+
allowRemote: !isModelCacheReady(contextOSDataDir()),
|
|
484
|
+
skills: scanSkills({ cwd: skillCwd, roots: [sourceDir] })
|
|
485
|
+
})
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
console.log("");
|
|
490
|
+
console.log("╭─ ContextOS is ready ───────────────────────────────────────╮");
|
|
491
|
+
console.log("│ Next: restart/open your agent from this project directory. │");
|
|
492
|
+
console.log("│ Try: ctx debug -- \"Recheck authen flow\" │");
|
|
493
|
+
console.log("╰───────────────────────────────────────────────────────────╯");
|
|
494
|
+
}
|
|
495
|
+
|
|
394
496
|
const args = process.argv.slice(2);
|
|
395
497
|
const command = args[0];
|
|
396
498
|
|
|
@@ -412,6 +514,8 @@ try {
|
|
|
412
514
|
inject: args.includes("--inject") || !args.includes("--quiet"),
|
|
413
515
|
agent: installAgentFromArgs(args)
|
|
414
516
|
});
|
|
517
|
+
} else if (command === "setup") {
|
|
518
|
+
await setup({ args: args.slice(1), cwd: process.cwd() });
|
|
415
519
|
} else if (command === "debug") {
|
|
416
520
|
const marker = args.indexOf("--");
|
|
417
521
|
const task = marker >= 0 ? args.slice(marker + 1).join(" ") : args.slice(1).join(" ");
|
|
@@ -451,6 +555,15 @@ try {
|
|
|
451
555
|
} else {
|
|
452
556
|
await syncRules({ cwd: process.cwd(), rootDir, args: args.slice(1) });
|
|
453
557
|
}
|
|
558
|
+
} else if (command === "ruler" || command === "skillshare") {
|
|
559
|
+
const passthrough = parsePassthroughArgs(args);
|
|
560
|
+
const result = runPassthrough(passthrough);
|
|
561
|
+
if (result.signal) {
|
|
562
|
+
console.error(`${passthrough.command} terminated by signal ${result.signal}`);
|
|
563
|
+
process.exitCode = 1;
|
|
564
|
+
} else {
|
|
565
|
+
process.exitCode = result.status;
|
|
566
|
+
}
|
|
454
567
|
} else {
|
|
455
568
|
throw new Error(`Unknown command: ${command}\n\n${usage()}`);
|
|
456
569
|
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
|
|
3
|
+
const SUPPORTED_COMMANDS = new Set(["ruler", "skillshare"]);
|
|
4
|
+
|
|
5
|
+
export function parsePassthroughArgs(args = []) {
|
|
6
|
+
const command = args[0];
|
|
7
|
+
if (!SUPPORTED_COMMANDS.has(command)) {
|
|
8
|
+
throw new Error(`Unsupported passthrough command: ${command || ""}`);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const separator = args.indexOf("--");
|
|
12
|
+
if (separator < 0) {
|
|
13
|
+
throw new Error(`Usage: ctx ${command} -- <${command} args>`);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
command,
|
|
18
|
+
args: args.slice(separator + 1)
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function runPassthrough({
|
|
23
|
+
command,
|
|
24
|
+
args = [],
|
|
25
|
+
spawn = spawnSync,
|
|
26
|
+
cwd = process.cwd(),
|
|
27
|
+
env = process.env
|
|
28
|
+
} = {}) {
|
|
29
|
+
if (!SUPPORTED_COMMANDS.has(command)) {
|
|
30
|
+
throw new Error(`Unsupported passthrough command: ${command || ""}`);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const result = spawn(command, args, {
|
|
34
|
+
cwd,
|
|
35
|
+
env,
|
|
36
|
+
stdio: "inherit"
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
if (result.error) {
|
|
40
|
+
const hint = command === "ruler"
|
|
41
|
+
? "Install it with `npm install -g @intellectronica/ruler`."
|
|
42
|
+
: "Install it with `curl -fsSL https://raw.githubusercontent.com/runkids/skillshare/main/install.sh | sh`.";
|
|
43
|
+
throw new Error(`Failed to run ${command}: ${result.error.message}. ${hint}`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
status: typeof result.status === "number" ? result.status : 1,
|
|
48
|
+
signal: result.signal || null
|
|
49
|
+
};
|
|
50
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
const DEFAULT_AGENTS = ["codex", "claude", "agy"];
|
|
2
|
+
|
|
3
|
+
export function parseSetupArgs(args = []) {
|
|
4
|
+
const agentsFlag = args.indexOf("--agents");
|
|
5
|
+
const agents = agentsFlag >= 0
|
|
6
|
+
? parseAgentList(args[agentsFlag + 1])
|
|
7
|
+
: DEFAULT_AGENTS;
|
|
8
|
+
|
|
9
|
+
return {
|
|
10
|
+
agents,
|
|
11
|
+
yes: args.includes("--yes") || args.includes("-y"),
|
|
12
|
+
quiet: args.includes("--quiet"),
|
|
13
|
+
inject: !args.includes("--quiet") && !args.includes("--no-inject"),
|
|
14
|
+
syncRules: !args.includes("--no-rules"),
|
|
15
|
+
syncSkills: !args.includes("--no-skills")
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function parseAgentList(value = "") {
|
|
20
|
+
const agents = String(value || "")
|
|
21
|
+
.split(",")
|
|
22
|
+
.map((item) => normalizeSetupAgent(item))
|
|
23
|
+
.filter(Boolean);
|
|
24
|
+
return [...new Set(agents)];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function normalizeSetupAgent(agent) {
|
|
28
|
+
const normalized = String(agent || "").trim().toLowerCase();
|
|
29
|
+
if (normalized === "antigravity") return "agy";
|
|
30
|
+
return normalized;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function setupSummaryLines({
|
|
34
|
+
cwd = process.cwd(),
|
|
35
|
+
agents = DEFAULT_AGENTS,
|
|
36
|
+
inject = true,
|
|
37
|
+
syncRules = true,
|
|
38
|
+
syncSkills = true
|
|
39
|
+
} = {}) {
|
|
40
|
+
return [
|
|
41
|
+
`Installation directory: ${cwd}`,
|
|
42
|
+
`Agents: ${agents.join(", ") || "(none)"}`,
|
|
43
|
+
`Prompt context injection: ${inject ? "enabled" : "quiet logging only"}`,
|
|
44
|
+
`Ruler rule/MCP sync: ${syncRules ? "enabled" : "skipped"}`,
|
|
45
|
+
`skillshare skill sync: ${syncSkills ? "enabled" : "skipped"}`
|
|
46
|
+
];
|
|
47
|
+
}
|