@xevy/cli 0.1.1 → 0.1.3

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 (3) hide show
  1. package/README.md +27 -48
  2. package/bin/xevy.mjs +158 -141
  3. package/package.json +4 -10
package/README.md CHANGED
@@ -1,71 +1,50 @@
1
1
  # @xevy/cli
2
2
 
3
- The **`xevy`** command — one step to get Xevy working in your AI agent.
3
+ The **`xevy`** command — set up and launch the [pi](https://github.com/badlogic/pi-mono) agent with Xevy.
4
4
 
5
5
  ```bash
6
- npx @xevy/cli setup
6
+ npx @xevy/cli setup # one-time: install pi + the Xevy extension + your API key
7
+ npx @xevy/cli # open pi with the Xevy extension loaded
7
8
  ```
8
9
 
9
- `xevy setup` installs the **Xevy SDLC agent skills** and the **Xevy MCP server**
10
- into your user-global agent config, for [Cursor, Claude Code, and 50+ other
11
- agents](https://github.com/vercel-labs/skills#supported-agents).
10
+ ## `xevy setup`
12
11
 
13
- ## No API key OAuth like any MCP
12
+ 1. Installs the **pi agent** if it isn't already on your PATH.
13
+ 2. Downloads the Xevy pi extension (`xevy.ts`) into **`~/.xevy/extensions/`**.
14
+ 3. Asks for your **API key** and prints a **direct link to the API-keys tab** so
15
+ you can generate one in a couple of clicks, then stores it in
16
+ `~/.config/xevy/credentials` (mode `600`, never printed).
14
17
 
15
- The Xevy MCP server signs in with **OAuth**, completed inside your agent the
16
- first time it connects. There is no API key to find in a dashboard, paste, or
17
- store on disk.
18
+ The API-keys link opens **Settings Profile API keys** directly:
19
+ `https://xevy.ai/settings?section=profile&tab=api`.
18
20
 
19
- - **Cursor:** Settings → MCP → `xevy` → connect
20
- - **Claude Code:** browser sign-in on the first MCP call
21
+ ## `xevy`
21
22
 
22
- ## What it does (and doesn't)
23
-
24
- - ✅ Installs skills globally (`~/.cursor/skills`, `~/.claude/skills`, `~/.agents/skills`, …)
25
- - ✅ Writes the MCP server to your agent's **global** config
26
- - ❌ No per-repo files, no project detection, no repo linking
27
-
28
- To link a specific repository to a Xevy project later, run the bundled
29
- `xevy-setup` skill from inside your agent (it uses the MCP tools over OAuth).
30
-
31
- ## Install permanently
23
+ Opens pi, loading every `*.ts` extension in `~/.xevy/extensions` (`pi -e …`).
24
+ Any extra arguments are forwarded to pi:
32
25
 
33
26
  ```bash
34
- npm i -g @xevy/cli
35
- xevy setup
27
+ xevy # interactive pi session with Xevy
28
+ xevy "summarise this repo" # forwards the prompt to pi
36
29
  ```
37
30
 
31
+ ## `xevy pi` (alternative)
32
+
33
+ Installs the split **model + MCP** extensions (`xevy-model.ts`, `xevy-mcp.ts`)
34
+ into pi's own extensions dir and authenticates over **OAuth** (`/login xevy`) —
35
+ no API key. Use this instead of `setup` if you prefer OAuth and the hosted
36
+ `xevy/*` models + MCP tool bridge.
37
+
38
38
  ## Options
39
39
 
40
40
  ```
41
- xevy setup [options]
42
-
43
- -a, --agent <name> Target agent (repeatable). Default: cursor, claude-code
44
- --base <url> Xevy host (default: XEVY_BASE or https://xevy.ai)
45
- --skills-only Install skills only (skip MCP)
46
- --mcp-only Configure the OAuth MCP server only (skip skills)
47
- --copy Copy skill files instead of symlinking
48
- -v, --version Print the CLI version
49
- -h, --help Show help
41
+ --base <url> Xevy host (default: XEVY_BASE or https://xevy.ai)
42
+ -v, --version Print the CLI version
43
+ -h, --help Show help
50
44
  ```
51
45
 
52
- ### Examples
53
-
54
46
  ```bash
55
- npx @xevy/cli setup # skills + MCP, global
56
- npx @xevy/cli setup -a cursor # Cursor only
57
- npx @xevy/cli setup --mcp-only # just the OAuth MCP
58
- XEVY_BASE=https://xevy.vyte.dev npx @xevy/cli setup # non-default host
47
+ XEVY_BASE=https://xevy.vyte.dev npx @xevy/cli setup
59
48
  ```
60
49
 
61
- ## How it works
62
-
63
- Under the hood `xevy setup` drives two well-known primitives:
64
-
65
- - [`npx skills`](https://github.com/vercel-labs/skills) — installs the skills
66
- - [`npx add-mcp`](https://github.com/neondatabase/add-mcp) — writes the MCP config
67
-
68
- Skills are sourced from the pinned [`@xevy/skills`](https://www.npmjs.com/package/@xevy/skills)
69
- dependency, so this CLI stays in step with the published skills.
70
-
71
50
  Docs: <https://xevy.ai/docs/mcp>
package/bin/xevy.mjs CHANGED
@@ -2,47 +2,57 @@
2
2
  /**
3
3
  * @xevy/cli — the `xevy` command.
4
4
  *
5
- * `xevy setup` installs the Xevy SDLC agent skills and the Xevy MCP server
6
- * globally, for Cursor / Claude Code / 50+ agents. The MCP server authenticates
7
- * via OAuth (completed inside the agent on first connect) — there is NO API key
8
- * to find, paste, or store. No repo/project detection or linking happens here.
5
+ * xevy setup Install the pi agent (if missing), download the Xevy pi
6
+ * extension into ~/.xevy/extensions, and store your API key.
7
+ * xevy Open pi with the Xevy extensions from ~/.xevy/extensions.
8
+ * xevy pi (alt) Install the split model + MCP extensions into pi's own
9
+ * extensions dir, authenticated via OAuth.
9
10
  *
10
- * Under the hood it drives the same primitives the Xevy docs recommend:
11
- * `npx skills add <dir>` — copies/symlinks the skills into agent scopes
12
- * `npx add-mcp <url>` — writes the agent MCP config (OAuth on connect)
13
- * Skills are sourced from the pinned `@xevy/skills` dependency, so this CLI
14
- * stays in step with the published skills without duplicating them.
15
- *
16
- * Usage:
17
- * npx @xevy/cli setup Install skills + MCP globally (OAuth)
18
- * npx @xevy/cli setup -a cursor Only a specific agent (repeatable)
19
- * npx @xevy/cli setup --mcp-only Configure the OAuth MCP server only
20
- * npx @xevy/cli --version
11
+ * `xevy setup` is the default flow: it fetches `xevy.ts` from the server and
12
+ * asks for an API key (with a direct link to the exact page to generate one),
13
+ * stored in ~/.config/xevy/credentials. Then `xevy` launches pi with it.
21
14
  */
22
15
  import { spawnSync } from "node:child_process";
23
- import { createRequire } from "node:module";
24
16
  import fs from "node:fs";
25
17
  import os from "node:os";
26
18
  import path from "node:path";
19
+ import readline from "node:readline";
27
20
  import { fileURLToPath } from "node:url";
28
21
 
29
- const require = createRequire(import.meta.url);
30
22
  const here = path.dirname(fileURLToPath(import.meta.url));
31
23
  const pkgRoot = path.resolve(here, "..");
32
24
 
33
25
  const DEFAULT_BASE = "https://xevy.ai";
34
- const DEFAULT_AGENTS = ["cursor", "claude-code"];
35
26
  const isWindows = process.platform === "win32";
36
27
 
37
28
  const PI_PACKAGE = "@mariozechner/pi-coding-agent";
29
+ const PI_BIN = isWindows ? "pi.cmd" : "pi";
30
+
31
+ // Where `xevy setup` installs the extension and `xevy` loads it from.
32
+ const XEVY_EXTENSIONS_DIR = path.join(os.homedir(), ".xevy", "extensions");
33
+ const XEVY_EXTENSION_FILE = "xevy.ts";
34
+ const API_KEY_PREFIX = "xevy_pk_";
35
+
36
+ // Credentials file the xevy.ts extension reads (baseUrl + token).
37
+ const CREDENTIALS_DIR = path.join(
38
+ process.env.XDG_CONFIG_HOME || path.join(os.homedir(), ".config"),
39
+ "xevy",
40
+ );
41
+ const CREDENTIALS_FILE = path.join(CREDENTIALS_DIR, "credentials");
42
+
43
+ // `xevy pi` (alt flow) installs these into pi's own extensions dir over OAuth.
38
44
  const PI_EXTENSION_DIR = path.join(os.homedir(), ".pi", "agent", "extensions");
39
- // pi extensions installed by `xevy pi` — file name + a marker string used to
40
- // sanity-check the download isn't SPA HTML (wrong --base).
41
45
  const PI_EXTENSIONS = [
42
46
  { file: "xevy-model.ts", marker: "xevyModelExtension" },
43
47
  { file: "xevy-mcp.ts", marker: "xevyMcpExtension" },
44
48
  ];
45
49
 
50
+ function apiKeysUrl(base) {
51
+ // Direct link to the API keys tab (Profile → API keys), reachable without a
52
+ // project via the root Settings app.
53
+ return `${base}/settings?section=profile&tab=api`;
54
+ }
55
+
46
56
  function readCliVersion() {
47
57
  try {
48
58
  const pkg = JSON.parse(fs.readFileSync(path.join(pkgRoot, "package.json"), "utf-8"));
@@ -58,144 +68,65 @@ function die(msg) {
58
68
  }
59
69
 
60
70
  function usage() {
61
- console.log(`Xevy CLI — install Xevy agent skills + OAuth MCP.
71
+ console.log(`Xevy CLI
62
72
 
63
- xevy setup [options] Install skills + MCP globally (OAuth, no API key)
64
- xevy pi [options] Install the pi agent (if missing) + the xevy-model.ts extension
73
+ xevy Open pi with the Xevy extensions in ~/.xevy/extensions
74
+ xevy setup [--base u] Install pi (if missing) + the Xevy pi extension, store your API key
75
+ xevy pi [--base u] (alt) Install the split model + MCP extensions over OAuth
65
76
 
66
77
  Options:
67
- -a, --agent <name> Target agent (repeatable). Default: ${DEFAULT_AGENTS.join(", ")}
68
- --base <url> Xevy host (default: XEVY_BASE or ${DEFAULT_BASE})
69
- --skills-only Install skills only (skip MCP)
70
- --mcp-only Configure the OAuth MCP server only (skip skills)
71
- --copy Copy skill files instead of symlinking
72
- -v, --version Print the CLI version
73
- -h, --help Show this help
74
-
75
- Notes:
76
- • Everything installs to your user-global scope — no per-repo files, no
77
- project detection or linking.
78
- • The MCP server signs in with OAuth from inside your agent on first
79
- connect. There is no API key to paste.
78
+ --base <url> Xevy host (default: XEVY_BASE or ${DEFAULT_BASE})
79
+ -v, --version Print the CLI version
80
+ -h, --help Show this help
80
81
 
81
82
  Examples:
82
83
  npx @xevy/cli setup
83
- npx @xevy/cli setup -a cursor
84
- npx @xevy/cli pi
84
+ npx @xevy/cli
85
85
  XEVY_BASE=https://xevy.vyte.dev npx @xevy/cli setup`);
86
86
  }
87
87
 
88
88
  function parseArgv(argv) {
89
- const opts = {
90
- command: "setup",
91
- agents: [],
92
- base: process.env.XEVY_BASE?.replace(/\/$/, "") || DEFAULT_BASE,
93
- skillsOnly: false,
94
- mcpOnly: false,
95
- copy: false,
96
- };
97
-
89
+ const base = process.env.XEVY_BASE?.replace(/\/$/, "") || DEFAULT_BASE;
98
90
  const args = [...argv];
99
- if (args.length > 0 && !args[0].startsWith("-")) {
100
- const cmd = args.shift();
101
- if (cmd === "setup" || cmd === "pi") {
102
- opts.command = cmd;
103
- } else if (cmd === "help") {
104
- opts.command = "help";
105
- return opts;
106
- } else {
107
- die(`Unknown command: ${cmd}. Try \`xevy --help\`.`);
108
- }
109
- }
110
91
 
111
- while (args.length > 0) {
112
- const a = args.shift();
113
- if (a === "-h" || a === "--help") return { ...opts, command: "help" };
114
- if (a === "-v" || a === "--version") return { ...opts, command: "version" };
115
- if (a === "-a" || a === "--agent") {
116
- const v = args.shift();
117
- if (!v) die("Missing value for --agent");
118
- opts.agents.push(v);
119
- continue;
120
- }
121
- if (a === "--base") {
122
- const v = args.shift();
123
- if (!v) die("Missing value for --base");
124
- opts.base = v.replace(/\/$/, "");
125
- continue;
92
+ if (args.length === 0) return { command: "open", base, piArgs: [] };
93
+
94
+ const first = args[0];
95
+ if (first === "-h" || first === "--help" || first === "help") return { command: "help", base };
96
+ if (first === "-v" || first === "--version") return { command: "version", base };
97
+
98
+ if (first === "setup" || first === "pi") {
99
+ args.shift();
100
+ const opts = { command: first, base, piArgs: [] };
101
+ while (args.length > 0) {
102
+ const a = args.shift();
103
+ if (a === "--base") {
104
+ const v = args.shift();
105
+ if (!v) die("Missing value for --base");
106
+ opts.base = v.replace(/\/$/, "");
107
+ continue;
108
+ }
109
+ die(`Unknown option for \`xevy ${first}\`: ${a}. Try \`xevy --help\`.`);
126
110
  }
127
- if (a === "--skills-only") { opts.skillsOnly = true; continue; }
128
- if (a === "--mcp-only") { opts.mcpOnly = true; continue; }
129
- if (a === "--copy") { opts.copy = true; continue; }
130
- die(`Unknown option: ${a}. Try \`xevy --help\`.`);
111
+ return opts;
131
112
  }
132
113
 
133
- if (opts.skillsOnly && opts.mcpOnly) {
134
- die("--skills-only and --mcp-only are mutually exclusive.");
135
- }
136
- if (opts.agents.length === 0) opts.agents = [...DEFAULT_AGENTS];
137
- return opts;
138
- }
139
-
140
- function quoteArg(a) {
141
- return /[\s"]/.test(a) ? `"${a.replace(/"/g, '\\"')}"` : a;
114
+ // Anything else → open pi, forwarding the args through.
115
+ return { command: "open", base, piArgs: args };
142
116
  }
143
117
 
144
118
  function run(cmd, args, { label } = {}) {
145
119
  const title = label || [cmd, ...args].join(" ");
146
120
  console.log(`→ ${title}`);
147
121
  const command = isWindows && cmd === "npx" ? "npx.cmd" : cmd;
148
- const finalArgs = isWindows ? args.map(quoteArg) : args;
149
- const r = spawnSync(command, finalArgs, { stdio: "inherit", shell: isWindows, env: process.env });
122
+ const r = spawnSync(command, args, { stdio: "inherit", shell: isWindows, env: process.env });
150
123
  if (r.error) die(r.error.message);
151
124
  if (r.status !== 0) die(`Command failed (${r.status}): ${title}`);
152
125
  return r;
153
126
  }
154
127
 
155
- /** Resolve the on-disk root of the pinned @xevy/skills dependency. */
156
- function resolveSkillsRoot() {
157
- try {
158
- return path.dirname(require.resolve("@xevy/skills/package.json"));
159
- } catch {
160
- die("Could not locate the bundled @xevy/skills package. Reinstall @xevy/cli and try again.");
161
- }
162
- }
163
-
164
- function installSkills(opts) {
165
- const skillsRoot = resolveSkillsRoot();
166
- const args = ["--yes", "skills", "add", skillsRoot, "-g", "-y", "-s", "*"];
167
- if (opts.copy) args.push("--copy");
168
- for (const a of opts.agents) args.push("-a", a);
169
- run("npx", args, { label: "npx skills add (Xevy skills, global)" });
170
- }
171
-
172
- function installMcp(opts) {
173
- const mcpUrl = `${opts.base}/mcp`;
174
- const args = ["--yes", "add-mcp", mcpUrl, "-n", "xevy", "-g", "-y"];
175
- for (const a of opts.agents) args.push("-a", a);
176
- run("npx", args, { label: `npx add-mcp ${mcpUrl} (OAuth, global)` });
177
- }
178
-
179
- function setup(opts) {
180
- console.log("Setting up Xevy (global, OAuth — no API key)\n");
181
-
182
- if (!opts.mcpOnly) installSkills(opts);
183
- if (!opts.skillsOnly) installMcp(opts);
184
-
185
- console.log("\n✓ Xevy setup complete.");
186
- if (!opts.skillsOnly) {
187
- console.log(" • Complete OAuth in your agent on first connect:");
188
- console.log(" Cursor: Settings → MCP → xevy → connect");
189
- console.log(" Claude Code: browser sign-in on first MCP call");
190
- }
191
- if (opts.base !== DEFAULT_BASE) {
192
- console.log(` • Host: ${opts.base} (set XEVY_BASE in your agent env too, then restart).`);
193
- }
194
- console.log(` • Docs: ${opts.base}/docs/mcp`);
195
- }
196
-
197
128
  function hasPi() {
198
- const r = spawnSync(isWindows ? "pi.cmd" : "pi", ["--version"], { stdio: "ignore", shell: isWindows });
129
+ const r = spawnSync(PI_BIN, ["--version"], { stdio: "ignore", shell: isWindows });
199
130
  return !r.error && r.status === 0;
200
131
  }
201
132
 
@@ -207,12 +138,12 @@ function ensurePi() {
207
138
  console.log(`→ pi agent not found — installing ${PI_PACKAGE} globally…`);
208
139
  run("npm", ["install", "-g", PI_PACKAGE], { label: `npm install -g ${PI_PACKAGE}` });
209
140
  if (!hasPi()) {
210
- die("pi is still not on PATH after install. Ensure your npm global bin dir is on PATH, then re-run `xevy pi`.");
141
+ die("pi is still not on PATH after install. Ensure your npm global bin dir is on PATH, then re-run.");
211
142
  }
212
143
  }
213
144
 
214
- async function installExtension(opts, { file, marker }) {
215
- const url = `${opts.base}/${file}`;
145
+ async function downloadExtension(base, file, destDir, markers) {
146
+ const url = `${base}/${file}`;
216
147
  console.log(`→ Downloading ${url}`);
217
148
 
218
149
  let source;
@@ -225,14 +156,101 @@ async function installExtension(opts, { file, marker }) {
225
156
  }
226
157
 
227
158
  // Guard against a wrong --base returning the SPA HTML instead of the extension.
228
- if (!source.includes(marker) || !source.includes("registerCommand")) {
159
+ if (!markers.every((m) => source.includes(m))) {
229
160
  die(`Downloaded ${url} does not look like the ${file} extension (wrong --base?).`);
230
161
  }
231
162
 
232
- fs.mkdirSync(PI_EXTENSION_DIR, { recursive: true });
233
- const dest = path.join(PI_EXTENSION_DIR, file);
163
+ fs.mkdirSync(destDir, { recursive: true });
164
+ const dest = path.join(destDir, file);
234
165
  fs.writeFileSync(dest, source, "utf-8");
235
166
  console.log(`✓ Installed ${dest}`);
167
+ return dest;
168
+ }
169
+
170
+ function promptLine(question) {
171
+ return new Promise((resolve) => {
172
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
173
+ rl.question(question, (answer) => {
174
+ rl.close();
175
+ resolve(String(answer || "").trim());
176
+ });
177
+ });
178
+ }
179
+
180
+ function writeCredentials(base, token) {
181
+ fs.mkdirSync(CREDENTIALS_DIR, { recursive: true });
182
+ fs.writeFileSync(
183
+ CREDENTIALS_FILE,
184
+ `baseUrl=${base}\ntoken=${token}\nupdatedAt=${new Date().toISOString()}\n`,
185
+ { mode: 0o600 },
186
+ );
187
+ try {
188
+ fs.chmodSync(CREDENTIALS_FILE, 0o600);
189
+ } catch {
190
+ // best-effort on platforms without chmod
191
+ }
192
+ }
193
+
194
+ async function setup(opts) {
195
+ console.log("Setting up Xevy for pi\n");
196
+
197
+ // 1. Ensure pi is installed (installs it if missing).
198
+ ensurePi();
199
+
200
+ // 2. Extensions:
201
+ // • xevy.ts → ~/.xevy/extensions (tools/workflow; loaded by `xevy`)
202
+ // • xevy-model.ts → pi's GLOBAL extensions dir, so the xevy/* models are
203
+ // available in EVERY pi session (plain `pi` too), not just via `xevy`.
204
+ await downloadExtension(opts.base, XEVY_EXTENSION_FILE, XEVY_EXTENSIONS_DIR, [
205
+ "EXTENSION_VERSION",
206
+ "registerCommand",
207
+ ]);
208
+ await downloadExtension(opts.base, "xevy-model.ts", PI_EXTENSION_DIR, [
209
+ "xevyModelExtension",
210
+ "registerCommand",
211
+ ]);
212
+
213
+ // 2. API key — with a direct link to the exact page to generate one.
214
+ console.log("\nGet your API key (this link opens the API keys tab directly):");
215
+ console.log(` ${apiKeysUrl(opts.base)}`);
216
+ console.log(" Sign in if prompted, then click “Create API key” and copy it.\n");
217
+
218
+ const token = await promptLine(`Paste your Xevy API key (${API_KEY_PREFIX}…): `);
219
+ if (!token) die("API key is required. Re-run `xevy setup` when you have one.");
220
+ if (!token.startsWith(API_KEY_PREFIX)) {
221
+ die(`That doesn't look like a Xevy API key (expected '${API_KEY_PREFIX}…'). Not saved.`);
222
+ }
223
+ writeCredentials(opts.base, token);
224
+ console.log(`✓ API key stored at ${CREDENTIALS_FILE} (key not shown).`);
225
+
226
+ console.log("\n✓ Setup complete.");
227
+ console.log(" • Xevy models (xevy/auto, xevy/fast, …) are available in any pi session — no /login needed.");
228
+ console.log(" • Run `xevy` to open pi with the Xevy tools + models loaded.");
229
+ if (opts.base !== DEFAULT_BASE) console.log(` • Host: ${opts.base}`);
230
+ }
231
+
232
+ function open(opts) {
233
+ if (!hasPi()) {
234
+ die("pi is not installed. Run `xevy setup` first.");
235
+ }
236
+ let files = [];
237
+ if (fs.existsSync(XEVY_EXTENSIONS_DIR)) {
238
+ files = fs
239
+ .readdirSync(XEVY_EXTENSIONS_DIR)
240
+ .filter((f) => f.endsWith(".ts"))
241
+ .map((f) => path.join(XEVY_EXTENSIONS_DIR, f));
242
+ }
243
+ if (files.length === 0) {
244
+ die(`No Xevy extensions in ${XEVY_EXTENSIONS_DIR}. Run \`xevy setup\` first.`);
245
+ }
246
+
247
+ const piArgs = [];
248
+ for (const f of files) piArgs.push("-e", f);
249
+ piArgs.push(...opts.piArgs);
250
+
251
+ const r = spawnSync(PI_BIN, piArgs, { stdio: "inherit", shell: isWindows, env: process.env });
252
+ if (r.error) die(r.error.message);
253
+ process.exit(r.status ?? 0);
236
254
  }
237
255
 
238
256
  async function piSetup(opts) {
@@ -240,7 +258,7 @@ async function piSetup(opts) {
240
258
 
241
259
  ensurePi();
242
260
  for (const ext of PI_EXTENSIONS) {
243
- await installExtension(opts, ext);
261
+ await downloadExtension(opts.base, ext.file, PI_EXTENSION_DIR, [ext.marker, "registerCommand"]);
244
262
  }
245
263
 
246
264
  console.log("\n✓ pi + Xevy extensions ready.");
@@ -248,9 +266,7 @@ async function piSetup(opts) {
248
266
  console.log(" • Xevy models: xevy/auto, xevy/fast, xevy/advance, xevy/min, xevy/max, xevy/vision.");
249
267
  console.log(" • MCP tools bridge automatically on session start (or run /xevy-mcp).");
250
268
  console.log(" • If pi is already running, use /reload to load the extensions.");
251
- if (opts.base !== DEFAULT_BASE) {
252
- console.log(` • Source host: ${opts.base}`);
253
- }
269
+ if (opts.base !== DEFAULT_BASE) console.log(` • Source host: ${opts.base}`);
254
270
  }
255
271
 
256
272
  async function main() {
@@ -260,6 +276,7 @@ async function main() {
260
276
  if (opts.command === "version") return console.log(readCliVersion());
261
277
  if (opts.command === "setup") return setup(opts);
262
278
  if (opts.command === "pi") return piSetup(opts);
279
+ if (opts.command === "open") return open(opts);
263
280
  }
264
281
 
265
282
  main().catch((error) => die(error instanceof Error ? error.message : String(error)));
package/package.json CHANGED
@@ -1,17 +1,14 @@
1
1
  {
2
2
  "name": "@xevy/cli",
3
- "version": "0.1.1",
4
- "description": "Xevy CLI — one command (`xevy setup`) installs the Xevy SDLC agent skills and the OAuth MCP server globally for Cursor, Claude Code, and 50+ agents. No API key required.",
3
+ "version": "0.1.3",
4
+ "description": "Xevy CLI — `xevy setup` installs the pi agent + the Xevy pi extension and stores your API key; `xevy` opens pi with it.",
5
5
  "type": "module",
6
6
  "keywords": [
7
7
  "xevy",
8
8
  "cli",
9
9
  "setup",
10
- "mcp",
11
- "oauth",
12
- "agent-skills",
13
- "cursor",
14
- "claude-code",
10
+ "pi",
11
+ "pi-agent",
15
12
  "sdlc"
16
13
  ],
17
14
  "homepage": "https://xevy.ai/docs/mcp",
@@ -26,9 +23,6 @@
26
23
  "engines": {
27
24
  "node": ">=18"
28
25
  },
29
- "dependencies": {
30
- "@xevy/skills": "^0.1.18"
31
- },
32
26
  "publishConfig": {
33
27
  "access": "public"
34
28
  }