@pulsemcp/air-cli 0.0.1
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/README.md +47 -0
- package/dist/adapter-registry.d.ts +11 -0
- package/dist/adapter-registry.d.ts.map +1 -0
- package/dist/adapter-registry.js +52 -0
- package/dist/adapter-registry.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +52 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/list.d.ts +3 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +138 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/start.d.ts +3 -0
- package/dist/commands/start.d.ts.map +1 -0
- package/dist/commands/start.js +112 -0
- package/dist/commands/start.js.map +1 -0
- package/dist/commands/validate.d.ts +3 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +62 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/package.json +43 -0
package/README.md
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# @pulsemcp/air-cli
|
|
2
|
+
|
|
3
|
+
CLI for the [AIR](https://github.com/pulsemcp/air) framework. Validates configs, lists artifacts, initializes new setups, and starts agent sessions.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @pulsemcp/air-cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Commands
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# Initialize a new AIR configuration at ~/.air/
|
|
15
|
+
air init
|
|
16
|
+
|
|
17
|
+
# Validate a JSON file against its AIR schema
|
|
18
|
+
air validate ~/.air/air.json
|
|
19
|
+
air validate ~/.air/mcp/mcp.json
|
|
20
|
+
|
|
21
|
+
# List available artifacts
|
|
22
|
+
air list skills
|
|
23
|
+
air list mcp
|
|
24
|
+
air list roots
|
|
25
|
+
|
|
26
|
+
# Start an agent session
|
|
27
|
+
air start claude
|
|
28
|
+
air start claude --root web-app
|
|
29
|
+
air start claude --root web-app --dry-run
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Agent Adapters
|
|
33
|
+
|
|
34
|
+
`air start <agent>` discovers adapters dynamically. Install the adapter package for your agent:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# Claude Code (officially maintained)
|
|
38
|
+
npm install -g @pulsemcp/air-adapter-claude
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The CLI looks for `@pulsemcp/air-adapter-<agent>` packages. If the package is installed, the agent is available.
|
|
42
|
+
|
|
43
|
+
## Environment Variables
|
|
44
|
+
|
|
45
|
+
| Variable | Description |
|
|
46
|
+
|----------|-------------|
|
|
47
|
+
| `AIR_CONFIG` | Override the path to `air.json` (default: `~/.air/air.json`) |
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { AgentAdapter } from "@pulsemcp/air-core";
|
|
2
|
+
/**
|
|
3
|
+
* Find an adapter by agent name.
|
|
4
|
+
* Returns null if the adapter package isn't installed.
|
|
5
|
+
*/
|
|
6
|
+
export declare function findAdapter(name: string): Promise<AgentAdapter | null>;
|
|
7
|
+
/**
|
|
8
|
+
* List all available adapter names (installed packages only).
|
|
9
|
+
*/
|
|
10
|
+
export declare function listAvailableAdapters(): Promise<string[]>;
|
|
11
|
+
//# sourceMappingURL=adapter-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter-registry.d.ts","sourceRoot":"","sources":["../src/adapter-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAgB,MAAM,oBAAoB,CAAC;AAUrE;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAsB9B;AAED;;GAEG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAW/D"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Known adapter packages. The CLI tries to dynamically import each one.
|
|
3
|
+
* If the package is installed, its adapter is available. If not, it's skipped.
|
|
4
|
+
*/
|
|
5
|
+
const KNOWN_ADAPTERS = [
|
|
6
|
+
{ name: "claude", packageName: "@pulsemcp/air-adapter-claude" },
|
|
7
|
+
];
|
|
8
|
+
/**
|
|
9
|
+
* Find an adapter by agent name.
|
|
10
|
+
* Returns null if the adapter package isn't installed.
|
|
11
|
+
*/
|
|
12
|
+
export async function findAdapter(name) {
|
|
13
|
+
// Check known adapters first
|
|
14
|
+
for (const known of KNOWN_ADAPTERS) {
|
|
15
|
+
if (known.name === name) {
|
|
16
|
+
try {
|
|
17
|
+
const mod = await import(known.packageName);
|
|
18
|
+
const ext = mod.default;
|
|
19
|
+
return ext?.adapter ?? null;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
// Try convention-based package name: @pulsemcp/air-adapter-{name}
|
|
27
|
+
try {
|
|
28
|
+
const mod = await import(`@pulsemcp/air-adapter-${name}`);
|
|
29
|
+
const ext = mod.default;
|
|
30
|
+
return ext?.adapter ?? null;
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* List all available adapter names (installed packages only).
|
|
38
|
+
*/
|
|
39
|
+
export async function listAvailableAdapters() {
|
|
40
|
+
const available = [];
|
|
41
|
+
for (const known of KNOWN_ADAPTERS) {
|
|
42
|
+
try {
|
|
43
|
+
await import(known.packageName);
|
|
44
|
+
available.push(known.name);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// Not installed
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return available;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=adapter-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter-registry.js","sourceRoot":"","sources":["../src/adapter-registry.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,cAAc,GAA4C;IAC9D,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,8BAA8B,EAAE;CAChE,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAY;IAEZ,6BAA6B;IAC7B,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;QACnC,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;YACxB,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;gBAC5C,MAAM,GAAG,GAAG,GAAG,CAAC,OAAmC,CAAC;gBACpD,OAAO,GAAG,EAAE,OAAO,IAAI,IAAI,CAAC;YAC9B,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;IACH,CAAC;IAED,kEAAkE;IAClE,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,yBAAyB,IAAI,EAAE,CAAC,CAAC;QAC1D,MAAM,GAAG,GAAG,GAAG,CAAC,OAAmC,CAAC;QACpD,OAAO,GAAG,EAAE,OAAO,IAAI,IAAI,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB;IACzC,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;QACnC,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;YAChC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7B,CAAC;QAAC,MAAM,CAAC;YACP,gBAAgB;QAClB,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,wBAAgB,WAAW,IAAI,OAAO,CA4DrC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { writeFileSync, existsSync, mkdirSync } from "fs";
|
|
3
|
+
import { resolve, dirname } from "path";
|
|
4
|
+
import { getDefaultAirJsonPath } from "@pulsemcp/air-core";
|
|
5
|
+
export function initCommand() {
|
|
6
|
+
const cmd = new Command("init")
|
|
7
|
+
.description("Initialize a new AIR configuration at ~/.air/")
|
|
8
|
+
.action(() => {
|
|
9
|
+
const airJsonPath = getDefaultAirJsonPath();
|
|
10
|
+
const airDir = dirname(airJsonPath);
|
|
11
|
+
if (existsSync(airJsonPath)) {
|
|
12
|
+
console.error(`Error: ${airJsonPath} already exists.`);
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
mkdirSync(airDir, { recursive: true });
|
|
16
|
+
const airJson = {
|
|
17
|
+
name: "my-config",
|
|
18
|
+
description: "",
|
|
19
|
+
skills: ["./skills/skills.json"],
|
|
20
|
+
references: ["./references/references.json"],
|
|
21
|
+
mcp: ["./mcp/mcp.json"],
|
|
22
|
+
plugins: ["./plugins/plugins.json"],
|
|
23
|
+
roots: ["./roots/roots.json"],
|
|
24
|
+
hooks: ["./hooks/hooks.json"],
|
|
25
|
+
};
|
|
26
|
+
const emptyIndex = () => "{}\n";
|
|
27
|
+
writeFileSync(airJsonPath, JSON.stringify(airJson, null, 2) + "\n");
|
|
28
|
+
const files = [
|
|
29
|
+
["skills/skills.json", emptyIndex()],
|
|
30
|
+
["references/references.json", emptyIndex()],
|
|
31
|
+
["mcp/mcp.json", emptyIndex()],
|
|
32
|
+
["plugins/plugins.json", emptyIndex()],
|
|
33
|
+
["roots/roots.json", emptyIndex()],
|
|
34
|
+
["hooks/hooks.json", emptyIndex()],
|
|
35
|
+
];
|
|
36
|
+
for (const [filename, content] of files) {
|
|
37
|
+
const filePath = resolve(airDir, filename);
|
|
38
|
+
mkdirSync(dirname(filePath), { recursive: true });
|
|
39
|
+
if (!existsSync(filePath)) {
|
|
40
|
+
writeFileSync(filePath, content);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
console.log(`Initialized AIR configuration at ${airDir}/:`);
|
|
44
|
+
console.log(" air.json");
|
|
45
|
+
for (const [filename] of files) {
|
|
46
|
+
console.log(` ${filename}`);
|
|
47
|
+
}
|
|
48
|
+
console.log("\nEdit air.json to configure your setup. Run 'air validate ~/.air/air.json' to check.");
|
|
49
|
+
});
|
|
50
|
+
return cmd;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACxC,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,MAAM,UAAU,WAAW;IACzB,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;SAC5B,WAAW,CAAC,+CAA+C,CAAC;SAC5D,MAAM,CAAC,GAAG,EAAE;QACX,MAAM,WAAW,GAAG,qBAAqB,EAAE,CAAC;QAC5C,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;QAEpC,IAAI,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAC5B,OAAO,CAAC,KAAK,CAAC,UAAU,WAAW,kBAAkB,CAAC,CAAC;YACvD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAEvC,MAAM,OAAO,GAAG;YACd,IAAI,EAAE,WAAW;YACjB,WAAW,EAAE,EAAE;YACf,MAAM,EAAE,CAAC,sBAAsB,CAAC;YAChC,UAAU,EAAE,CAAC,8BAA8B,CAAC;YAC5C,GAAG,EAAE,CAAC,gBAAgB,CAAC;YACvB,OAAO,EAAE,CAAC,wBAAwB,CAAC;YACnC,KAAK,EAAE,CAAC,oBAAoB,CAAC;YAC7B,KAAK,EAAE,CAAC,oBAAoB,CAAC;SAC9B,CAAC;QAEF,MAAM,UAAU,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC;QAEhC,aAAa,CACX,WAAW,EACX,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CACxC,CAAC;QAEF,MAAM,KAAK,GAAuB;YAChC,CAAC,oBAAoB,EAAE,UAAU,EAAE,CAAC;YACpC,CAAC,4BAA4B,EAAE,UAAU,EAAE,CAAC;YAC5C,CAAC,cAAc,EAAE,UAAU,EAAE,CAAC;YAC9B,CAAC,sBAAsB,EAAE,UAAU,EAAE,CAAC;YACtC,CAAC,kBAAkB,EAAE,UAAU,EAAE,CAAC;YAClC,CAAC,kBAAkB,EAAE,UAAU,EAAE,CAAC;SACnC,CAAC;QAEF,KAAK,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,KAAK,EAAE,CAAC;YACxC,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YAC3C,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAClD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC1B,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACnC,CAAC;QACH,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,oCAAoC,MAAM,IAAI,CAAC,CAAC;QAC5D,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAC1B,KAAK,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,EAAE,CAAC;YAC/B,OAAO,CAAC,GAAG,CAAC,KAAK,QAAQ,EAAE,CAAC,CAAC;QAC/B,CAAC;QACD,OAAO,CAAC,GAAG,CACT,uFAAuF,CACxF,CAAC;IACJ,CAAC,CAAC,CAAC;IAEL,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAwBpC,wBAAgB,WAAW,IAAI,OAAO,CAsJrC"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { getAirJsonPath, resolveArtifacts, emptyArtifacts, } from "@pulsemcp/air-core";
|
|
3
|
+
const VALID_TYPES = [
|
|
4
|
+
"skills",
|
|
5
|
+
"mcp",
|
|
6
|
+
"plugins",
|
|
7
|
+
"roots",
|
|
8
|
+
"hooks",
|
|
9
|
+
"references",
|
|
10
|
+
];
|
|
11
|
+
export function listCommand() {
|
|
12
|
+
const cmd = new Command("list")
|
|
13
|
+
.description("List available artifacts (skills, mcp, plugins, roots, hooks, references)")
|
|
14
|
+
.argument("<type>", "Artifact type to list: skills, mcp, plugins, roots, hooks, references")
|
|
15
|
+
.action(async (type) => {
|
|
16
|
+
if (!VALID_TYPES.includes(type)) {
|
|
17
|
+
console.error(`Error: Unknown artifact type "${type}". Valid types: ${VALID_TYPES.join(", ")}`);
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
const airJsonPath = getAirJsonPath();
|
|
21
|
+
const artifacts = airJsonPath
|
|
22
|
+
? await resolveArtifacts(airJsonPath)
|
|
23
|
+
: emptyArtifacts();
|
|
24
|
+
const listType = type;
|
|
25
|
+
switch (listType) {
|
|
26
|
+
case "skills": {
|
|
27
|
+
const entries = Object.entries(artifacts.skills);
|
|
28
|
+
if (entries.length === 0) {
|
|
29
|
+
console.log("No skills found.");
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
console.log(`Skills (${entries.length}):\n`);
|
|
33
|
+
for (const [id, skill] of entries) {
|
|
34
|
+
const title = skill.title ? ` (${skill.title})` : "";
|
|
35
|
+
console.log(` ${id}${title}`);
|
|
36
|
+
console.log(` ${skill.description}`);
|
|
37
|
+
if (skill.references && skill.references.length > 0) {
|
|
38
|
+
console.log(` References: ${skill.references.join(", ")}`);
|
|
39
|
+
}
|
|
40
|
+
console.log();
|
|
41
|
+
}
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
case "mcp": {
|
|
45
|
+
const entries = Object.entries(artifacts.mcp);
|
|
46
|
+
if (entries.length === 0) {
|
|
47
|
+
console.log("No MCP servers found.");
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
console.log(`MCP Servers (${entries.length}):\n`);
|
|
51
|
+
for (const [id, server] of entries) {
|
|
52
|
+
const title = server.title ? ` (${server.title})` : "";
|
|
53
|
+
console.log(` ${id}${title}`);
|
|
54
|
+
if (server.description) {
|
|
55
|
+
console.log(` ${server.description}`);
|
|
56
|
+
}
|
|
57
|
+
console.log(` Type: ${server.type}`);
|
|
58
|
+
console.log();
|
|
59
|
+
}
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
case "plugins": {
|
|
63
|
+
const entries = Object.entries(artifacts.plugins);
|
|
64
|
+
if (entries.length === 0) {
|
|
65
|
+
console.log("No plugins found.");
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
console.log(`Plugins (${entries.length}):\n`);
|
|
69
|
+
for (const [id, plugin] of entries) {
|
|
70
|
+
const title = plugin.title ? ` (${plugin.title})` : "";
|
|
71
|
+
console.log(` ${id}${title}`);
|
|
72
|
+
console.log(` ${plugin.description}`);
|
|
73
|
+
console.log(` Command: ${plugin.command} ${(plugin.args || []).join(" ")}`);
|
|
74
|
+
console.log();
|
|
75
|
+
}
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
case "roots": {
|
|
79
|
+
const entries = Object.entries(artifacts.roots);
|
|
80
|
+
if (entries.length === 0) {
|
|
81
|
+
console.log("No roots found.");
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
console.log(`Roots (${entries.length}):\n`);
|
|
85
|
+
for (const [id, root] of entries) {
|
|
86
|
+
const displayName = root.display_name || id;
|
|
87
|
+
console.log(` ${id} (${displayName})`);
|
|
88
|
+
console.log(` ${root.description}`);
|
|
89
|
+
if (root.url) {
|
|
90
|
+
console.log(` URL: ${root.url}`);
|
|
91
|
+
}
|
|
92
|
+
if (root.default_mcp_servers?.length) {
|
|
93
|
+
console.log(` MCP Servers: ${root.default_mcp_servers.join(", ")}`);
|
|
94
|
+
}
|
|
95
|
+
if (root.default_skills?.length) {
|
|
96
|
+
console.log(` Skills: ${root.default_skills.join(", ")}`);
|
|
97
|
+
}
|
|
98
|
+
console.log();
|
|
99
|
+
}
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
case "hooks": {
|
|
103
|
+
const entries = Object.entries(artifacts.hooks);
|
|
104
|
+
if (entries.length === 0) {
|
|
105
|
+
console.log("No hooks found.");
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
console.log(`Hooks (${entries.length}):\n`);
|
|
109
|
+
for (const [id, hook] of entries) {
|
|
110
|
+
const title = hook.title ? ` (${hook.title})` : "";
|
|
111
|
+
console.log(` ${id}${title}`);
|
|
112
|
+
console.log(` ${hook.description}`);
|
|
113
|
+
console.log(` Event: ${hook.event}`);
|
|
114
|
+
console.log();
|
|
115
|
+
}
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
case "references": {
|
|
119
|
+
const entries = Object.entries(artifacts.references);
|
|
120
|
+
if (entries.length === 0) {
|
|
121
|
+
console.log("No references found.");
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
console.log(`References (${entries.length}):\n`);
|
|
125
|
+
for (const [id, ref] of entries) {
|
|
126
|
+
const title = ref.title ? ` (${ref.title})` : "";
|
|
127
|
+
console.log(` ${id}${title}`);
|
|
128
|
+
console.log(` ${ref.description}`);
|
|
129
|
+
console.log(` File: ${ref.file}`);
|
|
130
|
+
console.log();
|
|
131
|
+
}
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
return cmd;
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,wBAAgB,YAAY,IAAI,OAAO,CAkFtC"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { getAirJsonPath, resolveArtifacts, emptyArtifacts, } from "@pulsemcp/air-core";
|
|
3
|
+
import { findAdapter, listAvailableAdapters } from "../adapter-registry.js";
|
|
4
|
+
export function startCommand() {
|
|
5
|
+
const cmd = new Command("start")
|
|
6
|
+
.description("Start an agent session with AIR configs loaded")
|
|
7
|
+
.argument("<agent>", "Agent to start (e.g., claude)")
|
|
8
|
+
.option("--root <name>", "Root to start the session in")
|
|
9
|
+
.option("--dry-run", "Show what would be activated without starting")
|
|
10
|
+
.option("--skip-confirmation", "Don't prompt for confirmation before starting")
|
|
11
|
+
.action(async (agent, options) => {
|
|
12
|
+
// Try to find the adapter
|
|
13
|
+
const adapter = await findAdapter(agent);
|
|
14
|
+
if (!adapter) {
|
|
15
|
+
const available = await listAvailableAdapters();
|
|
16
|
+
const availableMsg = available.length > 0
|
|
17
|
+
? `Available: ${available.join(", ")}`
|
|
18
|
+
: "No adapters installed";
|
|
19
|
+
console.error(`Error: No adapter found for "${agent}". ${availableMsg}.\n` +
|
|
20
|
+
`Install an adapter: npm install @pulsemcp/air-adapter-${agent}`);
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
// Load air.json
|
|
24
|
+
const airJsonPath = getAirJsonPath();
|
|
25
|
+
const artifacts = airJsonPath
|
|
26
|
+
? await resolveArtifacts(airJsonPath)
|
|
27
|
+
: emptyArtifacts();
|
|
28
|
+
// Resolve root if specified
|
|
29
|
+
let root;
|
|
30
|
+
if (options.root) {
|
|
31
|
+
root = artifacts.roots[options.root];
|
|
32
|
+
if (!root) {
|
|
33
|
+
console.error(`Error: Root "${options.root}" not found. Available roots: ${Object.keys(artifacts.roots).join(", ") || "(none)"}`);
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// Generate config
|
|
38
|
+
const sessionConfig = adapter.generateConfig(artifacts, root);
|
|
39
|
+
// Dry run
|
|
40
|
+
if (options.dryRun) {
|
|
41
|
+
printDryRun(agent, artifacts, root);
|
|
42
|
+
process.exit(0);
|
|
43
|
+
}
|
|
44
|
+
// Check if agent is available
|
|
45
|
+
const available = await adapter.isAvailable();
|
|
46
|
+
if (!available) {
|
|
47
|
+
console.error(`Error: ${adapter.displayName} is not installed or not in PATH.`);
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
printDryRun(agent, artifacts, root);
|
|
51
|
+
const startCmd = adapter.buildStartCommand(sessionConfig);
|
|
52
|
+
console.log(`\nStarting ${adapter.displayName}...`);
|
|
53
|
+
console.log(`Command: ${startCmd.command} ${startCmd.args.join(" ")}`);
|
|
54
|
+
});
|
|
55
|
+
return cmd;
|
|
56
|
+
}
|
|
57
|
+
function printDryRun(agent, artifacts, root) {
|
|
58
|
+
console.log(`\n=== AIR Session Configuration ===`);
|
|
59
|
+
console.log(`Agent: ${agent}`);
|
|
60
|
+
if (root) {
|
|
61
|
+
console.log(`Root: ${root.name} \u2014 ${root.description}`);
|
|
62
|
+
}
|
|
63
|
+
const mcpIds = root?.default_mcp_servers || Object.keys(artifacts.mcp);
|
|
64
|
+
const skillIds = root?.default_skills || Object.keys(artifacts.skills);
|
|
65
|
+
const pluginIds = root?.default_plugins || Object.keys(artifacts.plugins);
|
|
66
|
+
const hookIds = root?.default_hooks || Object.keys(artifacts.hooks);
|
|
67
|
+
console.log(`\nMCP Servers (${mcpIds.length}):`);
|
|
68
|
+
for (const id of mcpIds) {
|
|
69
|
+
const server = artifacts.mcp[id];
|
|
70
|
+
if (server) {
|
|
71
|
+
console.log(` \u2022 ${id} \u2014 ${server.description || server.title || "(no description)"}`);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
console.log(` \u2022 ${id} \u2014 (not found)`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
console.log(`\nSkills (${skillIds.length}):`);
|
|
78
|
+
for (const id of skillIds) {
|
|
79
|
+
const skill = artifacts.skills[id];
|
|
80
|
+
if (skill) {
|
|
81
|
+
console.log(` \u2022 ${id} \u2014 ${skill.description}`);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
console.log(` \u2022 ${id} \u2014 (not found)`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (pluginIds.length > 0) {
|
|
88
|
+
console.log(`\nPlugins (${pluginIds.length}):`);
|
|
89
|
+
for (const id of pluginIds) {
|
|
90
|
+
const plugin = artifacts.plugins[id];
|
|
91
|
+
if (plugin) {
|
|
92
|
+
console.log(` \u2022 ${id} \u2014 ${plugin.description}`);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
console.log(` \u2022 ${id} \u2014 (not found)`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (hookIds.length > 0) {
|
|
100
|
+
console.log(`\nHooks (${hookIds.length}):`);
|
|
101
|
+
for (const id of hookIds) {
|
|
102
|
+
const hook = artifacts.hooks[id];
|
|
103
|
+
if (hook) {
|
|
104
|
+
console.log(` \u2022 ${id} \u2014 ${hook.description}`);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
console.log(` \u2022 ${id} \u2014 (not found)`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=start.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWpC,wBAAgB,eAAe,IAAI,OAAO,CA2EzC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { readFileSync } from "fs";
|
|
3
|
+
import { resolve } from "path";
|
|
4
|
+
import { detectSchemaType, detectSchemaFromValue, isValidSchemaType, validateJson, } from "@pulsemcp/air-core";
|
|
5
|
+
export function validateCommand() {
|
|
6
|
+
const cmd = new Command("validate")
|
|
7
|
+
.description("Validate a JSON file against its AIR schema")
|
|
8
|
+
.argument("<file>", "Path to the JSON file to validate")
|
|
9
|
+
.option("--schema <type>", "Override schema detection (air, skills, references, mcp, plugins, roots, hooks)")
|
|
10
|
+
.action((file, options) => {
|
|
11
|
+
const filePath = resolve(process.cwd(), file);
|
|
12
|
+
let data;
|
|
13
|
+
try {
|
|
14
|
+
const content = readFileSync(filePath, "utf-8");
|
|
15
|
+
data = JSON.parse(content);
|
|
16
|
+
}
|
|
17
|
+
catch (err) {
|
|
18
|
+
const message = err instanceof Error ? err.message : "Unknown error";
|
|
19
|
+
console.error(`Error: Could not read or parse "${file}": ${message}`);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
// Determine schema type: --schema flag > $schema in JSON > filename substring
|
|
23
|
+
let schemaType = null;
|
|
24
|
+
if (options.schema) {
|
|
25
|
+
if (!isValidSchemaType(options.schema)) {
|
|
26
|
+
console.error(`Error: Unknown schema type "${options.schema}". Valid types: air, skills, references, mcp, plugins, roots, hooks`);
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
schemaType = options.schema;
|
|
30
|
+
}
|
|
31
|
+
if (!schemaType &&
|
|
32
|
+
data &&
|
|
33
|
+
typeof data === "object" &&
|
|
34
|
+
!Array.isArray(data)) {
|
|
35
|
+
const schemaValue = data.$schema;
|
|
36
|
+
if (typeof schemaValue === "string") {
|
|
37
|
+
schemaType = detectSchemaFromValue(schemaValue);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (!schemaType) {
|
|
41
|
+
schemaType = detectSchemaType(file);
|
|
42
|
+
}
|
|
43
|
+
if (!schemaType) {
|
|
44
|
+
console.error(`Error: Could not detect schema type for "${file}". Use --schema to specify.`);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
const result = validateJson(data, schemaType);
|
|
48
|
+
if (result.valid) {
|
|
49
|
+
console.log(`\u2713 ${file} is valid (schema: ${schemaType})`);
|
|
50
|
+
process.exit(0);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
console.error(`\u2717 ${file} has validation errors (schema: ${schemaType}):`);
|
|
54
|
+
for (const error of result.errors) {
|
|
55
|
+
console.error(` ${error.path}: ${error.message}`);
|
|
56
|
+
}
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
return cmd;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EACL,gBAAgB,EAChB,qBAAqB,EACrB,iBAAiB,EACjB,YAAY,GAEb,MAAM,oBAAoB,CAAC;AAE5B,MAAM,UAAU,eAAe;IAC7B,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,UAAU,CAAC;SAChC,WAAW,CAAC,6CAA6C,CAAC;SAC1D,QAAQ,CAAC,QAAQ,EAAE,mCAAmC,CAAC;SACvD,MAAM,CACL,iBAAiB,EACjB,iFAAiF,CAClF;SACA,MAAM,CAAC,CAAC,IAAY,EAAE,OAA4B,EAAE,EAAE;QACrD,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;QAE9C,IAAI,IAAa,CAAC;QAClB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAChD,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC7B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GACX,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;YACvD,OAAO,CAAC,KAAK,CAAC,mCAAmC,IAAI,MAAM,OAAO,EAAE,CAAC,CAAC;YACtE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,8EAA8E;QAC9E,IAAI,UAAU,GAAsB,IAAI,CAAC;QAEzC,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBACvC,OAAO,CAAC,KAAK,CACX,+BAA+B,OAAO,CAAC,MAAM,qEAAqE,CACnH,CAAC;gBACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;QAC9B,CAAC;QAED,IACE,CAAC,UAAU;YACX,IAAI;YACJ,OAAO,IAAI,KAAK,QAAQ;YACxB,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EACpB,CAAC;YACD,MAAM,WAAW,GAAI,IAAgC,CAAC,OAAO,CAAC;YAC9D,IAAI,OAAO,WAAW,KAAK,QAAQ,EAAE,CAAC;gBACpC,UAAU,GAAG,qBAAqB,CAAC,WAAW,CAAC,CAAC;YAClD,CAAC;QACH,CAAC;QAED,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,UAAU,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACtC,CAAC;QAED,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO,CAAC,KAAK,CACX,4CAA4C,IAAI,6BAA6B,CAC9E,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAE9C,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,sBAAsB,UAAU,GAAG,CAAC,CAAC;YAC/D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CACX,UAAU,IAAI,mCAAmC,UAAU,IAAI,CAChE,CAAC;YACF,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAClC,OAAO,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YACrD,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,OAAO,GAAG,CAAC;AACb,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { validateCommand } from "./commands/validate.js";
|
|
4
|
+
import { startCommand } from "./commands/start.js";
|
|
5
|
+
import { listCommand } from "./commands/list.js";
|
|
6
|
+
import { initCommand } from "./commands/init.js";
|
|
7
|
+
const program = new Command();
|
|
8
|
+
program
|
|
9
|
+
.name("air")
|
|
10
|
+
.description("AIR \u2014 Agent Infrastructure Repository CLI")
|
|
11
|
+
.version("0.0.1");
|
|
12
|
+
program.addCommand(validateCommand());
|
|
13
|
+
program.addCommand(startCommand());
|
|
14
|
+
program.addCommand(listCommand());
|
|
15
|
+
program.addCommand(initCommand());
|
|
16
|
+
program.parseAsync();
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,KAAK,CAAC;KACX,WAAW,CAAC,gDAAgD,CAAC;KAC7D,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO,CAAC,UAAU,CAAC,eAAe,EAAE,CAAC,CAAC;AACtC,OAAO,CAAC,UAAU,CAAC,YAAY,EAAE,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;AAElC,OAAO,CAAC,UAAU,EAAE,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pulsemcp/air-cli",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/pulsemcp/air.git",
|
|
10
|
+
"directory": "packages/cli"
|
|
11
|
+
},
|
|
12
|
+
"description": "CLI for the AIR (Agent Infrastructure Repository) framework",
|
|
13
|
+
"type": "module",
|
|
14
|
+
"bin": {
|
|
15
|
+
"air": "./dist/index.js"
|
|
16
|
+
},
|
|
17
|
+
"main": "./dist/index.js",
|
|
18
|
+
"files": [
|
|
19
|
+
"dist/"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsc",
|
|
23
|
+
"dev": "tsx src/index.ts",
|
|
24
|
+
"test": "vitest run",
|
|
25
|
+
"test:watch": "vitest",
|
|
26
|
+
"lint": "tsc --noEmit"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@pulsemcp/air-core": "0.0.1",
|
|
30
|
+
"@pulsemcp/air-adapter-claude": "0.0.1",
|
|
31
|
+
"commander": "^12.1.0",
|
|
32
|
+
"chalk": "^5.3.0"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/node": "^22.10.0",
|
|
36
|
+
"tsx": "^4.19.0",
|
|
37
|
+
"typescript": "^5.7.0",
|
|
38
|
+
"vitest": "^2.1.0"
|
|
39
|
+
},
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">=18"
|
|
42
|
+
}
|
|
43
|
+
}
|