@agent-native/skills 0.1.1 → 0.2.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.
- package/dist/built-in-apps.d.ts +60 -0
- package/dist/built-in-apps.d.ts.map +1 -0
- package/dist/built-in-apps.js +105 -0
- package/dist/built-in-apps.js.map +1 -0
- package/dist/connect.d.ts +81 -0
- package/dist/connect.d.ts.map +1 -0
- package/dist/connect.js +352 -0
- package/dist/connect.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +273 -52
- package/dist/index.js.map +1 -1
- package/dist/mcp-config-writers.d.ts +104 -0
- package/dist/mcp-config-writers.d.ts.map +1 -0
- package/dist/mcp-config-writers.js +418 -0
- package/dist/mcp-config-writers.js.map +1 -0
- package/dist/telemetry.d.ts +13 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +115 -0
- package/dist/telemetry.js.map +1 -0
- package/package.json +5 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect.js","sourceRoot":"","sources":["../src/connect.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * MCP-server registration + authentication for `@agent-native/skills`.\n *\n * This is a dependency-free port of the MCP-config-writing + device-code/OAuth\n * flow that lives in `@agent-native/core`'s `cli/connect.ts`. The skills package\n * ships standalone (no `@agent-native/core` dependency), so this module\n * re-implements just the registration surface against the shared on-disk\n * writers in `./mcp-config-writers.js`. It writes the SAME config and speaks the\n * SAME device-code/OAuth protocol as core.\n *\n * Two client families, exactly as in core:\n * - OAuth-capable (claude-code, claude-code-cli): get a URL-only HTTP MCP\n * entry (no bearer headers). The user authenticates in-host via standard\n * remote MCP OAuth: restart Claude Code, run /mcp, choose Authenticate.\n * - Device-code (codex, cowork): run the browser device-code flow against the\n * descriptor's hosted URL, then write the entry WITH the minted bearer token\n * + headers. Non-interactive (or no TTY) skips the flow and writes a\n * URL-only entry, surfacing the exact `agent-native connect <url> --token`\n * fallback command.\n *\n * Server contract (identical paths + JSON field names to core):\n * POST <hostedUrl>/_agent-native/mcp/connect/device/start (no auth)\n * body { client?, app? }\n * → { device_code, user_code, verification_uri,\n * verification_uri_complete, interval, expires_in }\n * POST <hostedUrl>/_agent-native/mcp/connect/device/poll (no auth)\n * body { device_code }\n * → { status: \"pending\" }\n * | { status: \"approved\", token, mcpUrl, serverName, mcpServerEntry }\n * | { status: \"expired\" } | { status: \"consumed\" }\n * | { status: \"error\" | \"not_found\", message? }\n *\n * Node-only. Node built-ins + global fetch only; no npm deps.\n */\n\nimport { ClientId, writeHttpEntryForClient } from \"./mcp-config-writers.js\";\n\nconst DEVICE_START_PATH = \"/_agent-native/mcp/connect/device/start\";\nconst DEVICE_POLL_PATH = \"/_agent-native/mcp/connect/device/poll\";\nconst MCP_PATH = \"/_agent-native/mcp\";\n\n/** OAuth-capable clients (in-host remote MCP OAuth, never a local bearer). */\nconst REMOTE_MCP_OAUTH_CLIENTS = new Set<ClientId>([\n \"claude-code\",\n \"claude-code-cli\",\n]);\n\n/** Identical to core: ask the deployed app to expose the full action catalog. */\nconst MCP_FULL_CATALOG_HEADER = \"X-Agent-Native-MCP-Full-Catalog\";\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\n/**\n * Describes one MCP server to register. `serverName` is the canonical config\n * key; `aliases` are additional config keys that point at the same MCP URL\n * (e.g. `plan` + `agent-native-plans`). `hostedUrl` is the deployed app origin\n * the device-code flow authenticates against; `mcpUrl` is the resolved MCP\n * endpoint written into the config (defaults to `<hostedUrl>/_agent-native/mcp`\n * when only `hostedUrl` is supplied).\n */\nexport interface McpDescriptor {\n serverName: string;\n mcpUrl: string;\n aliases?: string[];\n authMode?: \"oauth\" | \"device\" | \"none\";\n hostedUrl?: string;\n}\n\nexport interface RegisterMcpOptions {\n descriptor: McpDescriptor;\n clients: ClientId[];\n scope: \"user\" | \"project\";\n baseDir: string;\n interactive: boolean;\n log?: (m: string) => void;\n deps?: {\n fetchImpl?: typeof fetch;\n now?: () => number;\n sleep?: (ms: number) => Promise<void>;\n };\n}\n\nexport interface RegisterMcpResult {\n written: { client: ClientId; file: string }[];\n authenticated: boolean;\n guidance: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Device-code protocol shapes (field names match core EXACTLY).\n// ---------------------------------------------------------------------------\n\ninterface DeviceStartResponse {\n device_code: string;\n user_code: string;\n verification_uri: string;\n verification_uri_complete: string;\n interval?: number;\n expires_in?: number;\n}\n\ninterface DevicePollResponse {\n status:\n | \"pending\"\n | \"approved\"\n | \"expired\"\n | \"consumed\"\n | \"error\"\n | \"not_found\";\n token?: string;\n mcpUrl?: string;\n serverName?: string;\n mcpServerEntry?: Record<string, unknown>;\n message?: string;\n error?: string;\n}\n\ninterface DeviceGrant {\n token?: string;\n mcpUrl: string;\n serverName: string;\n headers?: Record<string, string>;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nexport function supportsRemoteMcpOAuth(client: ClientId): boolean {\n return REMOTE_MCP_OAUTH_CLIENTS.has(client);\n}\n\nfunction realSleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/** Trailing-slash-stripped origin+path for a hosted app URL. */\nfunction stripTrailingSlash(url: string): string {\n return url.replace(/\\/+$/, \"\");\n}\n\n/**\n * Resolve the MCP endpoint URL for a descriptor. Prefers an explicit `mcpUrl`,\n * otherwise derives `<hostedUrl>/_agent-native/mcp` (mirrors core's\n * `mcpUrlForBaseUrl`). Returns `undefined` when neither is usable.\n */\nfunction resolveMcpUrl(descriptor: McpDescriptor): string | undefined {\n if (descriptor.mcpUrl && descriptor.mcpUrl.trim()) {\n return descriptor.mcpUrl.trim();\n }\n if (descriptor.hostedUrl && descriptor.hostedUrl.trim()) {\n const base = stripTrailingSlash(descriptor.hostedUrl.trim());\n return `${base}${MCP_PATH}`;\n }\n return undefined;\n}\n\n/** Base (origin) URL of the deployed app the device flow runs against. */\nfunction resolveBaseUrl(descriptor: McpDescriptor): string | undefined {\n if (descriptor.hostedUrl && descriptor.hostedUrl.trim()) {\n return stripTrailingSlash(descriptor.hostedUrl.trim());\n }\n // Fall back to stripping the MCP path off an explicit mcpUrl.\n if (descriptor.mcpUrl && descriptor.mcpUrl.trim()) {\n const trimmed = stripTrailingSlash(descriptor.mcpUrl.trim());\n if (trimmed.endsWith(MCP_PATH)) {\n return trimmed.slice(0, -MCP_PATH.length);\n }\n }\n return undefined;\n}\n\n/** All config keys to register: the canonical name plus any aliases (deduped). */\nfunction configKeys(descriptor: McpDescriptor): string[] {\n const keys: string[] = [descriptor.serverName];\n for (const alias of descriptor.aliases ?? []) {\n if (alias && alias !== descriptor.serverName && !keys.includes(alias)) {\n keys.push(alias);\n }\n }\n return keys;\n}\n\n/** Always tag bearer-bearing entries so the client sees the full catalog. */\nfunction withFullCatalogHeader(\n headers: Record<string, string> | undefined,\n): Record<string, string> {\n return { ...(headers ?? {}), [MCP_FULL_CATALOG_HEADER]: \"1\" };\n}\n\nfunction responseMessage(json: any, fallback: string): string {\n const message =\n typeof json?.message === \"string\"\n ? json.message\n : typeof json?.error === \"string\"\n ? json.error\n : \"\";\n return message.trim() || fallback;\n}\n\nasync function postJson(\n fetchImpl: typeof fetch,\n url: string,\n body: unknown,\n): Promise<{ status: number; json: any }> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 30_000);\n try {\n const response = await fetchImpl(url, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(body ?? {}),\n signal: controller.signal,\n });\n let json: any = null;\n try {\n json = await response.json();\n } catch {\n json = null;\n }\n return { status: response.status, json };\n } finally {\n clearTimeout(timeout);\n }\n}\n\n/**\n * The exact no-browser fallback command core prints. Surfaced as guidance when\n * a device-code client is asked to register non-interactively.\n */\nfunction fallbackConnectCommand(baseUrl: string): string {\n return `npx @agent-native/core@latest connect ${baseUrl} --token <token>`;\n}\n\n/** Write a URL-only entry (no bearer) for every config key, collecting files. */\nfunction writeUrlOnlyEntries(\n clients: ClientId[],\n keys: string[],\n mcpUrl: string,\n scope: string,\n baseDir: string,\n written: { client: ClientId; file: string }[],\n errors: string[],\n): void {\n for (const client of clients) {\n for (const key of keys) {\n try {\n const file = writeHttpEntryForClient(\n client,\n key,\n mcpUrl,\n undefined,\n baseDir,\n scope,\n undefined,\n );\n written.push({ client, file });\n } catch (err: any) {\n errors.push(\n `Could not write ${key} for ${client}: ${err?.message ?? err}`,\n );\n }\n }\n }\n}\n\n/** Write a token+headers entry for every config key, collecting files. */\nfunction writeAuthedEntries(\n clients: ClientId[],\n keys: string[],\n mcpUrl: string,\n token: string | undefined,\n headers: Record<string, string> | undefined,\n scope: string,\n baseDir: string,\n written: { client: ClientId; file: string }[],\n errors: string[],\n): void {\n for (const client of clients) {\n for (const key of keys) {\n try {\n const file = writeHttpEntryForClient(\n client,\n key,\n mcpUrl,\n token,\n baseDir,\n scope,\n withFullCatalogHeader(headers),\n );\n written.push({ client, file });\n } catch (err: any) {\n errors.push(\n `Could not write ${key} for ${client}: ${err?.message ?? err}`,\n );\n }\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Device-code flow (dependency-free port of core's runDeviceFlow)\n// ---------------------------------------------------------------------------\n\n/**\n * Run the device-code flow against `baseUrl` and return the approved grant, or\n * `null` (after logging a clear message) on expiry/consumed/error/timeout. Same\n * state machine and field handling as core; the spinner/browser-open are\n * dropped since this runs inside a non-interactive installer context.\n */\nasync function runDeviceFlow(\n baseUrl: string,\n appSlug: string,\n clientArg: string,\n log: (m: string) => void,\n deps: RegisterMcpOptions[\"deps\"] = {},\n): Promise<DeviceGrant | null> {\n const fetchImpl = deps.fetchImpl ?? fetch;\n const sleep = deps.sleep ?? realSleep;\n const now = deps.now ?? (() => Date.now());\n\n let start: DeviceStartResponse;\n try {\n const { status, json } = await postJson(\n fetchImpl,\n `${baseUrl}${DEVICE_START_PATH}`,\n { client: clientArg, app: appSlug },\n );\n if (status < 200 || status >= 300 || !json?.device_code) {\n log(\n ` Could not start the connect flow on ${baseUrl} (HTTP ${status}). ` +\n `Is this an agent-native app, and is it deployed with the connect ` +\n `endpoint enabled?`,\n );\n return null;\n }\n start = json as DeviceStartResponse;\n } catch (err: any) {\n log(\n ` Could not reach ${baseUrl} (${err?.message ?? err}). ` +\n `Check the URL and your network.`,\n );\n return null;\n }\n\n const interval = Math.max(1, Number(start.interval) || 5);\n const expiresIn = Math.max(interval, Number(start.expires_in) || 600);\n const deadline = now() + expiresIn * 1000;\n\n log(\"\");\n log(` Connecting to ${baseUrl}`);\n log(\"\");\n log(` Your code: ${start.user_code}`);\n log(` Open: ${start.verification_uri_complete}`);\n log(\"\");\n log(\" Approve in the browser to finish.\");\n\n while (now() < deadline) {\n let poll: DevicePollResponse;\n try {\n const { status, json } = await postJson(\n fetchImpl,\n `${baseUrl}${DEVICE_POLL_PATH}`,\n { device_code: start.device_code },\n );\n if (status < 200 || status >= 300) {\n log(\n ` Connect polling failed (HTTP ${status}): ` +\n responseMessage(json, \"server returned an error.\"),\n );\n return null;\n }\n poll = (json ?? { status: \"pending\" }) as DevicePollResponse;\n } catch {\n // Transient network error — keep polling until the deadline.\n poll = { status: \"pending\" };\n }\n\n if (poll.status === \"approved\") {\n const token = poll.token ?? \"\";\n const mcpUrl = poll.mcpUrl ?? `${baseUrl}${MCP_PATH}`;\n const serverName = poll.serverName ?? appSlug;\n const headers =\n poll.mcpServerEntry &&\n typeof poll.mcpServerEntry === \"object\" &&\n poll.mcpServerEntry.headers &&\n typeof poll.mcpServerEntry.headers === \"object\"\n ? (poll.mcpServerEntry.headers as Record<string, string>)\n : undefined;\n log(\" Approved.\");\n return { token: token || undefined, mcpUrl, serverName, headers };\n }\n if (poll.status === \"expired\") {\n log(\" The connect request expired before it was approved.\");\n log(\" Run the command again to retry.\");\n return null;\n }\n if (poll.status === \"consumed\") {\n log(\" This connect code was already used. Run the command again.\");\n return null;\n }\n if (poll.status === \"error\" || poll.status === \"not_found\") {\n log(\n ` Connect polling failed: ${responseMessage(\n poll,\n poll.status === \"not_found\"\n ? \"device code was not found.\"\n : \"server returned an error.\",\n )}`,\n );\n return null;\n }\n\n await sleep(interval * 1000);\n }\n\n log(\" Timed out waiting for approval. Run the command again to retry.\");\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Public entry point\n// ---------------------------------------------------------------------------\n\n/**\n * Register an MCP server (plus aliases) into the requested client configs,\n * authenticating device-code clients via the browser flow when interactive.\n *\n * Idempotent: re-running replaces the same named entries. Never throws on a\n * single client/key failing — failures are collected into `guidance`.\n */\nexport async function registerMcpServer(\n opts: RegisterMcpOptions,\n): Promise<RegisterMcpResult> {\n const { descriptor, scope, baseDir, interactive } = opts;\n const log = opts.log ?? (() => {});\n const deps = opts.deps ?? {};\n\n const written: { client: ClientId; file: string }[] = [];\n const guidance: string[] = [];\n const errors: string[] = [];\n let authenticated = false;\n\n const keys = configKeys(descriptor);\n const mcpUrl = resolveMcpUrl(descriptor);\n if (!mcpUrl) {\n return {\n written,\n authenticated,\n guidance: [\n `Cannot register \"${descriptor.serverName}\": no mcpUrl or hostedUrl supplied.`,\n ],\n };\n }\n\n const authMode = descriptor.authMode ?? \"device\";\n\n // authMode \"none\" (e.g. context-xray): URL-only for ALL clients, no auth.\n if (authMode === \"none\") {\n writeUrlOnlyEntries(\n opts.clients,\n keys,\n mcpUrl,\n scope,\n baseDir,\n written,\n errors,\n );\n return { written, authenticated, guidance: [...guidance, ...errors] };\n }\n\n // Split into OAuth-capable and device-code clients, exactly like core.\n const oauthClients = opts.clients.filter((c) => supportsRemoteMcpOAuth(c));\n const deviceClients = opts.clients.filter((c) => !supportsRemoteMcpOAuth(c));\n\n // OAuth clients always get URL-only entries (in-host OAuth, no local bearer).\n if (oauthClients.length > 0) {\n writeUrlOnlyEntries(\n oauthClients,\n keys,\n mcpUrl,\n scope,\n baseDir,\n written,\n errors,\n );\n guidance.push(\n `${describeClients(oauthClients)}: wrote URL-only MCP config (no bearer headers).`,\n \"Next: restart Claude Code, run /mcp, and choose Authenticate.\",\n );\n }\n\n // Device-code clients.\n if (deviceClients.length > 0) {\n const baseUrl = resolveBaseUrl(descriptor);\n\n // We only reach here for authMode \"oauth\"/\"device\" (authMode \"none\" returned\n // earlier). Run the flow only when interactive AND we have a hosted URL to\n // authenticate against; otherwise fall back to URL-only.\n const canRunFlow = interactive && !!baseUrl;\n\n if (!canRunFlow) {\n writeUrlOnlyEntries(\n deviceClients,\n keys,\n mcpUrl,\n scope,\n baseDir,\n written,\n errors,\n );\n if (baseUrl) {\n guidance.push(\n `${describeClients(deviceClients)}: wrote URL-only MCP config (no token).`,\n `To authenticate non-interactively, run: ${fallbackConnectCommand(baseUrl)}`,\n );\n } else {\n guidance.push(\n `${describeClients(deviceClients)}: wrote URL-only MCP config (no hosted URL to authenticate against).`,\n );\n }\n } else {\n const appSlug = appSlugFor(descriptor, baseUrl!);\n const clientArg = deviceClients.length === 1 ? deviceClients[0] : \"all\";\n const grant = await runDeviceFlow(\n baseUrl!,\n appSlug,\n clientArg,\n log,\n deps,\n );\n\n if (grant && grant.token) {\n // Write authed entries; honour the server's resolved mcpUrl when given.\n const resolvedUrl = grant.mcpUrl || mcpUrl;\n writeAuthedEntries(\n deviceClients,\n keys,\n resolvedUrl,\n grant.token,\n grant.headers,\n scope,\n baseDir,\n written,\n errors,\n );\n authenticated = true;\n } else {\n // Flow failed (or approved with no token) — fall back to URL-only and\n // surface the exact recovery command.\n writeUrlOnlyEntries(\n deviceClients,\n keys,\n mcpUrl,\n scope,\n baseDir,\n written,\n errors,\n );\n guidance.push(\n `${describeClients(deviceClients)}: authentication did not complete; wrote URL-only MCP config.`,\n `To finish, run: ${fallbackConnectCommand(baseUrl!)}`,\n );\n }\n }\n }\n\n return { written, authenticated, guidance: [...guidance, ...errors] };\n}\n\nfunction describeClients(clients: ClientId[]): string {\n return clients.join(\", \");\n}\n\n/** Derive the `app` slug the device-start endpoint expects. */\nfunction appSlugFor(descriptor: McpDescriptor, baseUrl: string): string {\n // Prefer the descriptor's server name without the agent-native prefix.\n const name = descriptor.serverName.replace(/^agent-native-/, \"\");\n if (name) return name;\n try {\n const host = new URL(baseUrl).hostname;\n const first = host.split(\".\")[0];\n return first && first !== \"www\" ? first : \"app\";\n } catch {\n return \"app\";\n }\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type CliTelemetry } from "./telemetry.js";
|
|
1
2
|
export type SkillClient = "codex" | "claude-code";
|
|
2
3
|
export type SkillScope = "project" | "user";
|
|
3
4
|
export interface SkillEntry {
|
|
@@ -19,6 +20,21 @@ export interface InstallSkillsOptions {
|
|
|
19
20
|
force?: boolean;
|
|
20
21
|
log?: (message: string) => void;
|
|
21
22
|
isInteractive?: () => boolean;
|
|
23
|
+
telemetry?: CliTelemetry;
|
|
24
|
+
/**
|
|
25
|
+
* Register the hosted MCP server for app-backed skills (e.g. visual-plan /
|
|
26
|
+
* visual-recap → the Agent-Native Plan MCP). Defaults to `true`; pass
|
|
27
|
+
* `false` (CLI `--no-mcp`) to install the skill files only.
|
|
28
|
+
*/
|
|
29
|
+
mcp?: boolean;
|
|
30
|
+
}
|
|
31
|
+
export interface InstalledMcpServer {
|
|
32
|
+
serverName: string;
|
|
33
|
+
mcpUrl: string;
|
|
34
|
+
clients: SkillClient[];
|
|
35
|
+
files: string[];
|
|
36
|
+
authenticated: boolean;
|
|
37
|
+
guidance: string[];
|
|
22
38
|
}
|
|
23
39
|
export interface InstallSkillsResult {
|
|
24
40
|
source: string;
|
|
@@ -28,6 +44,7 @@ export interface InstallSkillsResult {
|
|
|
28
44
|
written: string[];
|
|
29
45
|
instructionFiles: string[];
|
|
30
46
|
githubActionPath?: string;
|
|
47
|
+
mcpServers: InstalledMcpServer[];
|
|
31
48
|
dryRun: boolean;
|
|
32
49
|
}
|
|
33
50
|
interface ParsedArgs {
|
|
@@ -46,6 +63,7 @@ interface ParsedArgs {
|
|
|
46
63
|
withGithubAction: boolean;
|
|
47
64
|
force: boolean;
|
|
48
65
|
baseDir?: string;
|
|
66
|
+
mcp: boolean;
|
|
49
67
|
}
|
|
50
68
|
export declare function parseSkillsCliArgs(argv: string[]): ParsedArgs;
|
|
51
69
|
export declare function runSkillsCli(argv: string[], options?: Pick<InstallSkillsOptions, "log" | "isInteractive" | "baseDir">): Promise<void>;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,10 @@ import fs from "node:fs";
|
|
|
4
4
|
import os from "node:os";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import readline from "node:readline/promises";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
import { resolveAppForSkill } from "./built-in-apps.js";
|
|
9
|
+
import { registerMcpServer } from "./connect.js";
|
|
10
|
+
import { createCliTelemetry } from "./telemetry.js";
|
|
7
11
|
const HELP = `@agent-native/skills
|
|
8
12
|
|
|
9
13
|
Usage:
|
|
@@ -21,10 +25,15 @@ Options:
|
|
|
21
25
|
--instructions-file <path> File to receive managed instructions (repeatable)
|
|
22
26
|
--with-github-action Add .github/workflows/pr-visual-recap.yml when visual-recap is installed
|
|
23
27
|
--force Overwrite a different existing PR Visual Recap workflow
|
|
28
|
+
--no-mcp Install skill files only; skip registering the app's MCP server
|
|
24
29
|
-y, --yes Use defaults in non-interactive mode
|
|
25
30
|
--dry-run Print intended writes without changing files
|
|
26
31
|
--json Print the result as JSON
|
|
27
32
|
|
|
33
|
+
App-backed skills (visual-plan, visual-recap, assets, design-exploration)
|
|
34
|
+
register their hosted MCP server in your agent config by default so the agent
|
|
35
|
+
can actually use them. Use --no-mcp to skip that and copy the files only.
|
|
36
|
+
|
|
28
37
|
Examples:
|
|
29
38
|
npx @agent-native/skills add
|
|
30
39
|
npx @agent-native/skills add --skill quick-recap
|
|
@@ -105,6 +114,10 @@ export function parseSkillsCliArgs(argv) {
|
|
|
105
114
|
out.withGithubAction = true;
|
|
106
115
|
else if (arg === "--force")
|
|
107
116
|
out.force = true;
|
|
117
|
+
else if (arg === "--no-mcp")
|
|
118
|
+
out.mcp = false;
|
|
119
|
+
else if (arg === "--mcp")
|
|
120
|
+
out.mcp = true;
|
|
108
121
|
else if (arg.startsWith("-"))
|
|
109
122
|
throw new Error(`Unknown option: ${arg}`);
|
|
110
123
|
else if (!out.source)
|
|
@@ -123,67 +136,183 @@ export function parseSkillsCliArgs(argv) {
|
|
|
123
136
|
out.instructionFiles = unique(out.instructionFiles);
|
|
124
137
|
return out;
|
|
125
138
|
}
|
|
139
|
+
/**
|
|
140
|
+
* Translate this package's parsed args into the argv shape `@agent-native/core`
|
|
141
|
+
* skills expects. Core takes a single positional target + compatible flags; we
|
|
142
|
+
* forward one explicit skill as that target and let core's interactive picker
|
|
143
|
+
* handle 0-or-many selections.
|
|
144
|
+
*/
|
|
145
|
+
function toCoreSkillsArgv(parsed) {
|
|
146
|
+
const out = [parsed.command];
|
|
147
|
+
if (parsed.command !== "add")
|
|
148
|
+
return out;
|
|
149
|
+
if (parsed.skillNames.length === 1)
|
|
150
|
+
out.push(parsed.skillNames[0]);
|
|
151
|
+
else if (parsed.copySource && parsed.source)
|
|
152
|
+
out.push(parsed.source);
|
|
153
|
+
if (parsed.clients.length)
|
|
154
|
+
out.push("--client", parsed.clients.join(","));
|
|
155
|
+
if (parsed.scopeExplicit)
|
|
156
|
+
out.push("--scope", parsed.scope);
|
|
157
|
+
if (parsed.yes)
|
|
158
|
+
out.push("--yes");
|
|
159
|
+
if (parsed.dryRun)
|
|
160
|
+
out.push("--dry-run");
|
|
161
|
+
if (parsed.printJson)
|
|
162
|
+
out.push("--json");
|
|
163
|
+
if (parsed.withGithubAction)
|
|
164
|
+
out.push("--with-github-action");
|
|
165
|
+
if (parsed.force)
|
|
166
|
+
out.push("--force");
|
|
167
|
+
if (parsed.mcp === false)
|
|
168
|
+
out.push("--no-mcp");
|
|
169
|
+
if (parsed.updateInstructions === true)
|
|
170
|
+
out.push("--update-instructions");
|
|
171
|
+
if (parsed.updateInstructions === false)
|
|
172
|
+
out.push("--no-update-instructions");
|
|
173
|
+
return out;
|
|
174
|
+
}
|
|
126
175
|
export async function runSkillsCli(argv, options = {}) {
|
|
127
176
|
const parsed = parseSkillsCliArgs(argv);
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
177
|
+
// PIVOT: `@agent-native/skills` delegates its install/list flow to
|
|
178
|
+
// `@agent-native/core`'s clack-based installer so both CLIs share ONE codebase
|
|
179
|
+
// and UX. App-backed skills (visual-plan/visual-recap/assets/design-exploration/
|
|
180
|
+
// context-xray) and the interactive picker go through core. Plain BuilderIO
|
|
181
|
+
// skills (efficient-fable, quick-recap, …) aren't known to core, so an explicit
|
|
182
|
+
// plain `--skill` falls through to this package's own headless installer.
|
|
183
|
+
// AGENT_NATIVE_SKILLS_DIRECT=1 (set when core delegates a plain repo back to us)
|
|
184
|
+
// always forces the direct path and breaks the skills → core → skills loop.
|
|
185
|
+
if (process.env.AGENT_NATIVE_SKILLS_DIRECT !== "1") {
|
|
186
|
+
const appOnly = parsed.skillNames.length === 0 ||
|
|
187
|
+
parsed.skillNames.every((name) => resolveAppForSkill(name) !== undefined);
|
|
188
|
+
if (parsed.command === "list" || (parsed.command === "add" && appOnly)) {
|
|
189
|
+
const { runSkills } = await import("@agent-native/core/cli/skills");
|
|
190
|
+
await runSkills(toCoreSkillsArgv(parsed), {
|
|
191
|
+
isInteractive: options.isInteractive,
|
|
192
|
+
baseDir: parsed.baseDir ?? options.baseDir,
|
|
193
|
+
});
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
131
196
|
}
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
197
|
+
const startedAt = Date.now();
|
|
198
|
+
const telemetry = createCliTelemetry({
|
|
199
|
+
cli: "skills-installer",
|
|
200
|
+
cliVersion: readCliVersion(),
|
|
201
|
+
command: parsed.command,
|
|
202
|
+
interactive: cliInteractive(parsed, options),
|
|
203
|
+
});
|
|
204
|
+
try {
|
|
205
|
+
if (parsed.command === "help") {
|
|
206
|
+
process.stdout.write(`${HELP}\n`);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
telemetry.track("skills_cli started");
|
|
210
|
+
const skillSource = parsed.source ?? DEFAULT_SKILLS_SOURCE;
|
|
211
|
+
if (parsed.command === "list") {
|
|
212
|
+
const source = await materializeSource(skillSource);
|
|
213
|
+
try {
|
|
214
|
+
const skills = discoverSkills(source.root);
|
|
215
|
+
telemetry.track("skills_cli skills listed", {
|
|
216
|
+
availableCount: skills.length,
|
|
217
|
+
available: skills.map((skill) => skill.name).join(","),
|
|
218
|
+
});
|
|
219
|
+
if (parsed.printJson) {
|
|
220
|
+
process.stdout.write(`${JSON.stringify(skills, null, 2)}\n`);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
for (const skill of skills) {
|
|
224
|
+
process.stdout.write(`${skill.name}${skill.description ? ` - ${skill.description}` : ""}\n`);
|
|
225
|
+
}
|
|
139
226
|
return;
|
|
140
227
|
}
|
|
141
|
-
|
|
142
|
-
|
|
228
|
+
finally {
|
|
229
|
+
source.cleanup?.();
|
|
143
230
|
}
|
|
144
|
-
return;
|
|
145
231
|
}
|
|
146
|
-
|
|
147
|
-
source
|
|
232
|
+
const result = await installSkills({
|
|
233
|
+
source: skillSource,
|
|
234
|
+
skillNames: parsed.skillNames,
|
|
235
|
+
clients: parsed.clients,
|
|
236
|
+
// Leave scope undefined unless the user passed --scope/-g/--project so the
|
|
237
|
+
// installer can prompt for it interactively.
|
|
238
|
+
scope: parsed.scopeExplicit ? parsed.scope : undefined,
|
|
239
|
+
baseDir: parsed.baseDir ?? options.baseDir,
|
|
240
|
+
yes: parsed.yes,
|
|
241
|
+
dryRun: parsed.dryRun,
|
|
242
|
+
updateInstructions: parsed.updateInstructions,
|
|
243
|
+
instructionFiles: parsed.instructionFiles,
|
|
244
|
+
withGithubAction: parsed.withGithubAction,
|
|
245
|
+
force: parsed.force,
|
|
246
|
+
log: parsed.printJson ? undefined : options.log,
|
|
247
|
+
isInteractive: options.isInteractive,
|
|
248
|
+
telemetry,
|
|
249
|
+
mcp: parsed.mcp,
|
|
250
|
+
});
|
|
251
|
+
telemetry.track("skills_cli completed", {
|
|
252
|
+
skills: result.skills.join(","),
|
|
253
|
+
clients: result.clients.join(","),
|
|
254
|
+
scope: result.scope,
|
|
255
|
+
dryRun: result.dryRun,
|
|
256
|
+
durationMs: Date.now() - startedAt,
|
|
257
|
+
});
|
|
258
|
+
if (parsed.printJson) {
|
|
259
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
260
|
+
return;
|
|
148
261
|
}
|
|
262
|
+
const verb = parsed.dryRun ? "Would install" : "Installed";
|
|
263
|
+
process.stdout.write([
|
|
264
|
+
`${verb} ${result.skills.join(", ")} for ${result.clients.join(", ")} (${result.scope}).`,
|
|
265
|
+
result.written.length
|
|
266
|
+
? `Skill files: ${result.written.join(", ")}`
|
|
267
|
+
: "",
|
|
268
|
+
result.instructionFiles.length
|
|
269
|
+
? `Managed instructions: ${result.instructionFiles.join(", ")}`
|
|
270
|
+
: "",
|
|
271
|
+
result.githubActionPath
|
|
272
|
+
? `PR Visual Recap workflow: ${result.githubActionPath}`
|
|
273
|
+
: "",
|
|
274
|
+
...result.mcpServers.flatMap((server) => [
|
|
275
|
+
`MCP server "${server.serverName}" ${parsed.dryRun ? "would be registered" : "registered"} for ${server.clients.join(", ")}${server.files.length ? `:\n ${server.files.join("\n ")}` : ""}`,
|
|
276
|
+
...server.guidance.map((line) => ` ${line}`),
|
|
277
|
+
]),
|
|
278
|
+
parsed.dryRun
|
|
279
|
+
? ""
|
|
280
|
+
: "Restart or reload selected agent clients if needed.",
|
|
281
|
+
]
|
|
282
|
+
.filter(Boolean)
|
|
283
|
+
.join("\n") + "\n");
|
|
284
|
+
}
|
|
285
|
+
catch (error) {
|
|
286
|
+
telemetry.track("skills_cli failed", {
|
|
287
|
+
command: parsed.command,
|
|
288
|
+
error: error instanceof Error ? error.message : String(error),
|
|
289
|
+
durationMs: Date.now() - startedAt,
|
|
290
|
+
});
|
|
291
|
+
throw error;
|
|
292
|
+
}
|
|
293
|
+
finally {
|
|
294
|
+
await telemetry.flush();
|
|
149
295
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
//
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
if (
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
}
|
|
171
|
-
const verb = parsed.dryRun ? "Would install" : "Installed";
|
|
172
|
-
process.stdout.write([
|
|
173
|
-
`${verb} ${result.skills.join(", ")} for ${result.clients.join(", ")} (${result.scope}).`,
|
|
174
|
-
result.written.length ? `Skill files: ${result.written.join(", ")}` : "",
|
|
175
|
-
result.instructionFiles.length
|
|
176
|
-
? `Managed instructions: ${result.instructionFiles.join(", ")}`
|
|
177
|
-
: "",
|
|
178
|
-
result.githubActionPath
|
|
179
|
-
? `PR Visual Recap workflow: ${result.githubActionPath}`
|
|
180
|
-
: "",
|
|
181
|
-
parsed.dryRun
|
|
182
|
-
? ""
|
|
183
|
-
: "Restart or reload selected agent clients if needed.",
|
|
184
|
-
]
|
|
185
|
-
.filter(Boolean)
|
|
186
|
-
.join("\n") + "\n");
|
|
296
|
+
}
|
|
297
|
+
function readCliVersion() {
|
|
298
|
+
try {
|
|
299
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
300
|
+
// dist/index.js → ../package.json
|
|
301
|
+
const pkg = JSON.parse(fs.readFileSync(path.resolve(here, "../package.json"), "utf8"));
|
|
302
|
+
return typeof pkg.version === "string" ? pkg.version : "unknown";
|
|
303
|
+
}
|
|
304
|
+
catch {
|
|
305
|
+
return "unknown";
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
function cliInteractive(parsed, options) {
|
|
309
|
+
if (parsed.yes)
|
|
310
|
+
return false;
|
|
311
|
+
if (options.isInteractive)
|
|
312
|
+
return options.isInteractive();
|
|
313
|
+
if (process.env.CI === "true")
|
|
314
|
+
return false;
|
|
315
|
+
return Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
187
316
|
}
|
|
188
317
|
export async function installSkills(options) {
|
|
189
318
|
const baseDir = path.resolve(options.baseDir ?? process.cwd());
|
|
@@ -195,9 +324,30 @@ export async function installSkills(options) {
|
|
|
195
324
|
if (entries.length === 0) {
|
|
196
325
|
throw new Error(`No skills found in ${sourceInput}. Expected skills/*/SKILL.md.`);
|
|
197
326
|
}
|
|
327
|
+
// Fire the "skills prompted" step only when an interactive chooser will
|
|
328
|
+
// actually be shown (mirrors resolveSelectedSkills's prompt condition), so
|
|
329
|
+
// the funnel distinguishes "saw the picker" from "passed --skill".
|
|
330
|
+
const preselected = (options.skillNames ?? []).length > 0;
|
|
331
|
+
if (isInteractive(options) && !options.yes && !preselected) {
|
|
332
|
+
options.telemetry?.track("skills_cli skills prompted", {
|
|
333
|
+
availableCount: entries.length,
|
|
334
|
+
available: entries.map((entry) => entry.name).join(","),
|
|
335
|
+
});
|
|
336
|
+
}
|
|
198
337
|
const selected = await resolveSelectedSkills(entries, options);
|
|
338
|
+
options.telemetry?.track("skills_cli skills selected", {
|
|
339
|
+
selected: selected.map((skill) => skill.name).join(","),
|
|
340
|
+
selectedCount: selected.length,
|
|
341
|
+
selectedAll: selected.length === entries.length,
|
|
342
|
+
preselected,
|
|
343
|
+
});
|
|
199
344
|
const clients = await resolveSelectedClients(options);
|
|
345
|
+
options.telemetry?.track("skills_cli clients selected", {
|
|
346
|
+
clients: clients.join(","),
|
|
347
|
+
clientCount: clients.length,
|
|
348
|
+
});
|
|
200
349
|
const scope = await resolveSelectedScope(options);
|
|
350
|
+
options.telemetry?.track("skills_cli scope selected", { scope });
|
|
201
351
|
const written = [];
|
|
202
352
|
for (const client of clients) {
|
|
203
353
|
const root = installRootForClient(client, scope, baseDir);
|
|
@@ -211,12 +361,81 @@ export async function installSkills(options) {
|
|
|
211
361
|
}
|
|
212
362
|
}
|
|
213
363
|
}
|
|
364
|
+
options.telemetry?.track("skills_cli install completed", {
|
|
365
|
+
skills: selected.map((skill) => skill.name).join(","),
|
|
366
|
+
clients: clients.join(","),
|
|
367
|
+
scope,
|
|
368
|
+
writtenCount: written.length,
|
|
369
|
+
dryRun: Boolean(options.dryRun),
|
|
370
|
+
});
|
|
214
371
|
const instructionFiles = await maybeUpdateInstructions(selected.map((skill) => skill.name), baseDir, options);
|
|
372
|
+
if (instructionFiles.length) {
|
|
373
|
+
options.telemetry?.track("skills_cli instructions updated", {
|
|
374
|
+
fileCount: instructionFiles.length,
|
|
375
|
+
});
|
|
376
|
+
}
|
|
215
377
|
const githubActionPath = selected.some((skill) => skill.name === "visual-recap") &&
|
|
216
378
|
(options.withGithubAction ||
|
|
217
379
|
(await shouldPromptGithubAction(options, baseDir)))
|
|
218
380
|
? writePrVisualRecapWorkflow(baseDir, options)
|
|
219
381
|
: undefined;
|
|
382
|
+
if (githubActionPath) {
|
|
383
|
+
options.telemetry?.track("skills_cli github action added");
|
|
384
|
+
}
|
|
385
|
+
// Register the hosted MCP server for app-backed skills (visual-plan /
|
|
386
|
+
// visual-recap → Agent-Native Plan, assets, design-exploration) so the
|
|
387
|
+
// agent can actually call them — not just read the SKILL.md. On by
|
|
388
|
+
// default; `--no-mcp` installs the skill files only. One registration per
|
|
389
|
+
// app, so visual-plan + visual-recap share a single "plan" server.
|
|
390
|
+
const mcpServers = [];
|
|
391
|
+
if (options.mcp !== false) {
|
|
392
|
+
const mcpClients = clients.map((client) => client === "claude-code" ? "claude-code" : "codex");
|
|
393
|
+
const seenApps = new Set();
|
|
394
|
+
for (const skill of selected) {
|
|
395
|
+
const app = resolveAppForSkill(skill.name);
|
|
396
|
+
if (!app || seenApps.has(app.appId))
|
|
397
|
+
continue;
|
|
398
|
+
seenApps.add(app.appId);
|
|
399
|
+
if (options.dryRun) {
|
|
400
|
+
mcpServers.push({
|
|
401
|
+
serverName: app.serverName,
|
|
402
|
+
mcpUrl: app.mcpUrl,
|
|
403
|
+
clients,
|
|
404
|
+
files: [],
|
|
405
|
+
authenticated: false,
|
|
406
|
+
guidance: [],
|
|
407
|
+
});
|
|
408
|
+
continue;
|
|
409
|
+
}
|
|
410
|
+
const registration = await registerMcpServer({
|
|
411
|
+
descriptor: {
|
|
412
|
+
serverName: app.serverName,
|
|
413
|
+
mcpUrl: app.mcpUrl,
|
|
414
|
+
aliases: app.aliases,
|
|
415
|
+
authMode: app.authMode,
|
|
416
|
+
hostedUrl: app.hostedUrl,
|
|
417
|
+
},
|
|
418
|
+
clients: mcpClients,
|
|
419
|
+
scope,
|
|
420
|
+
baseDir,
|
|
421
|
+
interactive: isInteractive(options),
|
|
422
|
+
log,
|
|
423
|
+
});
|
|
424
|
+
mcpServers.push({
|
|
425
|
+
serverName: app.serverName,
|
|
426
|
+
mcpUrl: app.mcpUrl,
|
|
427
|
+
clients,
|
|
428
|
+
files: [...new Set(registration.written.map((entry) => entry.file))],
|
|
429
|
+
authenticated: registration.authenticated,
|
|
430
|
+
guidance: registration.guidance,
|
|
431
|
+
});
|
|
432
|
+
options.telemetry?.track("skills_cli mcp registered", {
|
|
433
|
+
serverName: app.serverName,
|
|
434
|
+
clients: clients.join(","),
|
|
435
|
+
authenticated: registration.authenticated,
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
}
|
|
220
439
|
log(`Resolved ${selected.length} skill${selected.length === 1 ? "" : "s"} from ${source.root}.`);
|
|
221
440
|
return {
|
|
222
441
|
source: source.root,
|
|
@@ -226,6 +445,7 @@ export async function installSkills(options) {
|
|
|
226
445
|
written,
|
|
227
446
|
instructionFiles,
|
|
228
447
|
githubActionPath,
|
|
448
|
+
mcpServers,
|
|
229
449
|
dryRun: Boolean(options.dryRun),
|
|
230
450
|
};
|
|
231
451
|
}
|
|
@@ -247,6 +467,7 @@ function defaultArgs(command) {
|
|
|
247
467
|
instructionFiles: [],
|
|
248
468
|
withGithubAction: false,
|
|
249
469
|
force: false,
|
|
470
|
+
mcp: true,
|
|
250
471
|
};
|
|
251
472
|
}
|
|
252
473
|
function parseScope(value) {
|