x1pm 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.
Files changed (2) hide show
  1. package/dist/index.js +186 -0
  2. package/package.json +35 -0
package/dist/index.js ADDED
@@ -0,0 +1,186 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const USAGE = `Usage: x1pm <command> [options]
5
+
6
+ Commands:
7
+ ls List files and directories
8
+ read Read a file
9
+ write Create a new file
10
+ edit Edit a file (atomic string replacement)
11
+ multi-edit Batch edit multiple files
12
+ glob Find files by pattern
13
+ grep Search file contents
14
+ health Health check
15
+
16
+ Options:
17
+ --key <key> API key (or X1PM_API_KEY env var)
18
+ --server <url> Server URL (default: https://x1pm.com, or X1PM_SERVER env var)
19
+
20
+ Command options:
21
+ --path <path> File or directory path
22
+ --content <text> File content (for write; use "-" to read from stdin)
23
+ --old-str <text> String to find (for edit; use "-" to read from stdin)
24
+ --new-str <text> Replacement string (for edit; use "-" to read from stdin)
25
+ --pattern <pat> Search or glob pattern
26
+ --output-mode <m> Grep output mode: content | files_with_matches | count
27
+ --offset <n> Line offset (for read)
28
+ --limit <n> Line limit (for read)
29
+ --edits <json> JSON array of edits (for multi-edit)`;
30
+ function parseArgs(argv) {
31
+ const args = argv.slice(2);
32
+ const command = args[0] ?? "";
33
+ const flags = {};
34
+ for (let i = 1; i < args.length; i++) {
35
+ const arg = args[i];
36
+ if (arg.startsWith("--") && i + 1 < args.length) {
37
+ flags[arg.slice(2)] = args[++i];
38
+ }
39
+ }
40
+ return { command, flags };
41
+ }
42
+ async function readStdin() {
43
+ const chunks = [];
44
+ for await (const chunk of process.stdin) {
45
+ chunks.push(chunk);
46
+ }
47
+ return Buffer.concat(chunks).toString("utf-8");
48
+ }
49
+ async function resolveValue(value) {
50
+ if (value === "-")
51
+ return readStdin();
52
+ return value;
53
+ }
54
+ async function callApi(server, apiKey, fn, body) {
55
+ const url = `${server}/api/${fn}`;
56
+ const res = await fetch(url, {
57
+ method: "POST",
58
+ headers: {
59
+ "Content-Type": "application/json",
60
+ Authorization: `Bearer ${apiKey}`,
61
+ },
62
+ body: JSON.stringify(body),
63
+ });
64
+ if (!res.ok) {
65
+ const text = await res.text();
66
+ process.stderr.write(`Error (${res.status}): ${text}\n`);
67
+ process.exit(1);
68
+ }
69
+ return res.json();
70
+ }
71
+ async function main() {
72
+ const { command, flags } = parseArgs(process.argv);
73
+ if (!command || command === "help" || command === "--help" || command === "-h") {
74
+ console.log(USAGE);
75
+ process.exit(0);
76
+ }
77
+ const apiKey = flags["key"] ?? process.env.X1PM_API_KEY;
78
+ const server = (flags["server"] ?? process.env.X1PM_SERVER ?? "https://x1pm.com").replace(/\/$/, "");
79
+ if (!apiKey && command !== "health") {
80
+ process.stderr.write("Error: API key required. Set X1PM_API_KEY env var or pass --key.\n");
81
+ process.exit(1);
82
+ }
83
+ let result;
84
+ switch (command) {
85
+ case "health":
86
+ result = await callApi(server, apiKey ?? "", "healthCheck", {});
87
+ break;
88
+ case "ls":
89
+ result = await callApi(server, apiKey, "ls", {
90
+ path: flags["path"] ?? null,
91
+ });
92
+ break;
93
+ case "read":
94
+ if (!flags["path"]) {
95
+ process.stderr.write("Error: --path is required for read\n");
96
+ process.exit(1);
97
+ }
98
+ result = await callApi(server, apiKey, "read", {
99
+ path: flags["path"],
100
+ offset: flags["offset"] ? parseInt(flags["offset"], 10) : null,
101
+ limit: flags["limit"] ? parseInt(flags["limit"], 10) : null,
102
+ });
103
+ break;
104
+ case "write": {
105
+ if (!flags["path"]) {
106
+ process.stderr.write("Error: --path is required for write\n");
107
+ process.exit(1);
108
+ }
109
+ const content = await resolveValue(flags["content"]);
110
+ if (content === undefined) {
111
+ process.stderr.write("Error: --content is required for write\n");
112
+ process.exit(1);
113
+ }
114
+ result = await callApi(server, apiKey, "write", {
115
+ path: flags["path"],
116
+ content,
117
+ });
118
+ break;
119
+ }
120
+ case "edit": {
121
+ if (!flags["path"]) {
122
+ process.stderr.write("Error: --path is required for edit\n");
123
+ process.exit(1);
124
+ }
125
+ const oldStr = await resolveValue(flags["old-str"]);
126
+ const newStr = await resolveValue(flags["new-str"]);
127
+ if (oldStr === undefined || newStr === undefined) {
128
+ process.stderr.write("Error: --old-str and --new-str are required for edit\n");
129
+ process.exit(1);
130
+ }
131
+ result = await callApi(server, apiKey, "edit", {
132
+ path: flags["path"],
133
+ old_str: oldStr,
134
+ new_str: newStr,
135
+ });
136
+ break;
137
+ }
138
+ case "multi-edit": {
139
+ const editsJson = flags["edits"];
140
+ if (!editsJson) {
141
+ process.stderr.write("Error: --edits is required for multi-edit\n");
142
+ process.exit(1);
143
+ }
144
+ let edits;
145
+ try {
146
+ edits = JSON.parse(editsJson);
147
+ }
148
+ catch {
149
+ process.stderr.write("Error: --edits must be valid JSON\n");
150
+ process.exit(1);
151
+ }
152
+ result = await callApi(server, apiKey, "multiEdit", { edits });
153
+ break;
154
+ }
155
+ case "glob":
156
+ if (!flags["pattern"]) {
157
+ process.stderr.write("Error: --pattern is required for glob\n");
158
+ process.exit(1);
159
+ }
160
+ result = await callApi(server, apiKey, "glob", {
161
+ pattern: flags["pattern"],
162
+ path: flags["path"] ?? null,
163
+ });
164
+ break;
165
+ case "grep":
166
+ if (!flags["pattern"]) {
167
+ process.stderr.write("Error: --pattern is required for grep\n");
168
+ process.exit(1);
169
+ }
170
+ result = await callApi(server, apiKey, "grep", {
171
+ pattern: flags["pattern"],
172
+ path: flags["path"] ?? null,
173
+ output_mode: flags["output-mode"] ?? null,
174
+ });
175
+ break;
176
+ default:
177
+ process.stderr.write(`Unknown command: ${command}\n\n`);
178
+ console.log(USAGE);
179
+ process.exit(1);
180
+ }
181
+ console.log(JSON.stringify(result, null, 2));
182
+ }
183
+ main().catch((err) => {
184
+ process.stderr.write(`Error: ${err.message}\n`);
185
+ process.exit(1);
186
+ });
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "x1pm",
3
+ "version": "0.0.1",
4
+ "description": "CLI for x1pm - shared workspace for human-AI teams",
5
+ "bin": {
6
+ "x1pm": "./dist/index.js"
7
+ },
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "prepublishOnly": "npm run build"
14
+ },
15
+ "engines": {
16
+ "node": ">=18.0.0"
17
+ },
18
+ "keywords": [
19
+ "mcp",
20
+ "agent",
21
+ "workspace",
22
+ "claude-skill",
23
+ "collaboration"
24
+ ],
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "https://github.com/vanna-ai/x1pm.git",
28
+ "directory": "cli"
29
+ },
30
+ "license": "MIT",
31
+ "devDependencies": {
32
+ "typescript": "^5.0.0",
33
+ "@types/node": "^20.0.0"
34
+ }
35
+ }