@polterware/polter 0.4.0 → 0.4.2

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/api.js CHANGED
@@ -1,7 +1,10 @@
1
- import "./chunk-AGVTFYXU.js";
1
+ import {
2
+ createIpcClient
3
+ } from "./chunk-XCCKD3RZ.js";
2
4
  import {
3
5
  allCommands,
4
6
  applyActions,
7
+ createIpcServer,
5
8
  deletePipeline,
6
9
  detectPkgManager,
7
10
  executePipeline,
@@ -19,6 +22,9 @@ import {
19
22
  getFlagsForTool,
20
23
  getMcpStatusInfo,
21
24
  getProcessOutput,
25
+ getSkillContent,
26
+ getSkillPath,
27
+ getSocketPath,
22
28
  getToolDisplayName,
23
29
  getToolInfo,
24
30
  installMcpServerSilent,
@@ -26,20 +32,25 @@ import {
26
32
  listProcesses,
27
33
  parsePolterYaml,
28
34
  planChanges,
35
+ registerForegroundProcess,
29
36
  removeMcpServerSilent,
30
37
  removeProcess,
31
38
  resolvePkgArgs,
32
39
  resolveToolCommand,
33
40
  runCommand,
34
41
  savePipeline,
42
+ setupSkill,
43
+ setupSkillCli,
35
44
  startProcess,
36
45
  stopProcess,
37
46
  toolFlags,
38
47
  translateCommand
39
- } from "./chunk-YNOZDU75.js";
48
+ } from "./chunk-CWBIXRZP.js";
40
49
  export {
41
50
  allCommands,
42
51
  applyActions,
52
+ createIpcClient,
53
+ createIpcServer,
43
54
  deletePipeline,
44
55
  detectPkgManager,
45
56
  executePipeline,
@@ -57,6 +68,9 @@ export {
57
68
  getFlagsForTool,
58
69
  getMcpStatusInfo,
59
70
  getProcessOutput,
71
+ getSkillContent,
72
+ getSkillPath,
73
+ getSocketPath,
60
74
  getToolDisplayName,
61
75
  getToolInfo,
62
76
  installMcpServerSilent,
@@ -64,12 +78,15 @@ export {
64
78
  listProcesses,
65
79
  parsePolterYaml,
66
80
  planChanges,
81
+ registerForegroundProcess,
67
82
  removeMcpServerSilent,
68
83
  removeProcess,
69
84
  resolvePkgArgs,
70
85
  resolveToolCommand,
71
86
  runCommand,
72
87
  savePipeline,
88
+ setupSkill,
89
+ setupSkillCli,
73
90
  startProcess,
74
91
  stopProcess,
75
92
  toolFlags,
@@ -989,6 +989,7 @@ function runCommand(execution, args, cwd = process.cwd(), options) {
989
989
  cwd,
990
990
  env: resolvedExecution.env,
991
991
  shell: true,
992
+ detached: true,
992
993
  stdio: [options?.quiet ? "pipe" : "inherit", "pipe", "pipe"]
993
994
  });
994
995
  if (options?.quiet) {
@@ -1022,7 +1023,15 @@ function runCommand(execution, args, cwd = process.cwd(), options) {
1022
1023
  });
1023
1024
  return {
1024
1025
  promise,
1025
- abort: () => child.kill("SIGTERM")
1026
+ abort: () => {
1027
+ if (child.pid) {
1028
+ try {
1029
+ process.kill(-child.pid, "SIGTERM");
1030
+ } catch {
1031
+ }
1032
+ }
1033
+ },
1034
+ child
1026
1035
  };
1027
1036
  }
1028
1037
  function runInteractiveCommand(execution, args, cwd = process.cwd()) {
@@ -1337,6 +1346,31 @@ function getToolLinkInfo(toolId, cwd = process.cwd()) {
1337
1346
 
1338
1347
  // src/lib/processManager.ts
1339
1348
  import { spawn as spawn2 } from "child_process";
1349
+ import { join as join5 } from "path";
1350
+
1351
+ // src/lib/packageRoot.ts
1352
+ import { existsSync as existsSync4 } from "fs";
1353
+ import { dirname as dirname3, join as join4, resolve as resolve2 } from "path";
1354
+ var rootCache = /* @__PURE__ */ new Map();
1355
+ function findNearestPackageRoot(startDir = process.cwd()) {
1356
+ const resolvedStart = resolve2(startDir);
1357
+ if (rootCache.has(resolvedStart)) return rootCache.get(resolvedStart);
1358
+ let currentDir = resolvedStart;
1359
+ while (true) {
1360
+ if (existsSync4(join4(currentDir, "package.json"))) {
1361
+ rootCache.set(resolvedStart, currentDir);
1362
+ return currentDir;
1363
+ }
1364
+ const parentDir = dirname3(currentDir);
1365
+ if (parentDir === currentDir) {
1366
+ rootCache.set(resolvedStart, void 0);
1367
+ return void 0;
1368
+ }
1369
+ currentDir = parentDir;
1370
+ }
1371
+ }
1372
+
1373
+ // src/lib/processManager.ts
1340
1374
  var DEFAULT_BUFFER_CAP = 1e3;
1341
1375
  function createRingBuffer(cap = DEFAULT_BUFFER_CAP) {
1342
1376
  return { lines: [], cap, totalLines: 0 };
@@ -1437,6 +1471,47 @@ function startProcess(id, command, args = [], cwd = process.cwd(), env) {
1437
1471
  registry.set(id, tracked);
1438
1472
  return toProcessInfo(tracked);
1439
1473
  }
1474
+ function registerForegroundProcess(id, command, args, cwd, child) {
1475
+ const existing = registry.get(id);
1476
+ if (existing && existing.status === "running") {
1477
+ throw new Error(`Process "${id}" is already running (pid ${existing.child.pid})`);
1478
+ }
1479
+ registerCleanup();
1480
+ const tracked = {
1481
+ id,
1482
+ command,
1483
+ args,
1484
+ cwd,
1485
+ child,
1486
+ status: "running",
1487
+ exitCode: null,
1488
+ signal: null,
1489
+ startedAt: /* @__PURE__ */ new Date(),
1490
+ exitedAt: null,
1491
+ stdout: createRingBuffer(),
1492
+ stderr: createRingBuffer()
1493
+ };
1494
+ child.stdout?.on("data", (data) => {
1495
+ appendToBuffer(tracked.stdout, data.toString());
1496
+ });
1497
+ child.stderr?.on("data", (data) => {
1498
+ appendToBuffer(tracked.stderr, data.toString());
1499
+ });
1500
+ child.on("exit", (code, signal) => {
1501
+ tracked.status = "exited";
1502
+ tracked.exitCode = code;
1503
+ tracked.signal = signal;
1504
+ tracked.exitedAt = /* @__PURE__ */ new Date();
1505
+ });
1506
+ child.on("error", (err) => {
1507
+ tracked.status = "errored";
1508
+ tracked.exitedAt = /* @__PURE__ */ new Date();
1509
+ appendToBuffer(tracked.stderr, `spawn error: ${err.message}
1510
+ `);
1511
+ });
1512
+ registry.set(id, tracked);
1513
+ return toProcessInfo(tracked);
1514
+ }
1440
1515
  function stopProcess(id) {
1441
1516
  const proc = registry.get(id);
1442
1517
  if (!proc) throw new Error(`No tracked process with id "${id}"`);
@@ -1536,6 +1611,188 @@ function toProcessInfo(proc) {
1536
1611
  uptime: end - start
1537
1612
  };
1538
1613
  }
1614
+ function getSocketPath(cwd) {
1615
+ const root = findNearestPackageRoot(cwd);
1616
+ if (!root) return void 0;
1617
+ return join5(root, ".polter", "polter.sock");
1618
+ }
1619
+
1620
+ // src/lib/ipcServer.ts
1621
+ import net from "net";
1622
+ import { mkdirSync, unlinkSync, existsSync as existsSync5 } from "fs";
1623
+ import { dirname as dirname4 } from "path";
1624
+
1625
+ // src/lib/ipcProtocol.ts
1626
+ var DELIMITER = "\n";
1627
+ function serializeMessage(msg) {
1628
+ return JSON.stringify(msg) + DELIMITER;
1629
+ }
1630
+ function parseMessages(buffer) {
1631
+ const messages = [];
1632
+ let remainder = buffer;
1633
+ let idx;
1634
+ while ((idx = remainder.indexOf(DELIMITER)) !== -1) {
1635
+ const line = remainder.slice(0, idx);
1636
+ remainder = remainder.slice(idx + 1);
1637
+ if (line.length === 0) continue;
1638
+ try {
1639
+ messages.push(JSON.parse(line));
1640
+ } catch {
1641
+ }
1642
+ }
1643
+ return { messages, remainder };
1644
+ }
1645
+
1646
+ // src/lib/ipcServer.ts
1647
+ var handlers = {
1648
+ "ps.list": () => listProcesses(),
1649
+ "ps.start": (params) => {
1650
+ const { command, args, cwd, id } = params;
1651
+ const processArgs = args ?? [];
1652
+ const processId = id ?? generateProcessId(command, processArgs);
1653
+ const processCwd = cwd ?? process.cwd();
1654
+ return startProcess(processId, command, processArgs, processCwd);
1655
+ },
1656
+ "ps.stop": async (params) => {
1657
+ const { id } = params;
1658
+ return stopProcess(id);
1659
+ },
1660
+ "ps.logs": (params) => {
1661
+ const { id, tail, stream } = params;
1662
+ return getProcessOutput(id, tail, stream);
1663
+ },
1664
+ "ps.remove": (params) => {
1665
+ const { id } = params;
1666
+ removeProcess(id);
1667
+ return null;
1668
+ },
1669
+ "ps.find_by_cwd": (params) => {
1670
+ const { cwd, filter } = params;
1671
+ let processes = findProcessesByCwd(cwd);
1672
+ if (filter) {
1673
+ const f = filter.toLowerCase();
1674
+ processes = processes.filter(
1675
+ (p) => (p.command + " " + p.args.join(" ")).toLowerCase().includes(f)
1676
+ );
1677
+ }
1678
+ return processes;
1679
+ },
1680
+ "ps.find_running": (params) => {
1681
+ const { cwd, command, args } = params;
1682
+ return findRunningByCommand(cwd, command, args) ?? null;
1683
+ },
1684
+ "ps.generate_id": (params) => {
1685
+ const { command, args } = params;
1686
+ return generateProcessId(command, args);
1687
+ },
1688
+ status: () => ({ tui: true, pid: process.pid })
1689
+ };
1690
+ async function handleRequest(req) {
1691
+ const handler = handlers[req.method];
1692
+ if (!handler) {
1693
+ return {
1694
+ jsonrpc: "2.0",
1695
+ id: req.id,
1696
+ error: { code: -32601, message: `Method not found: ${req.method}` }
1697
+ };
1698
+ }
1699
+ try {
1700
+ const result = await handler(req.params ?? {});
1701
+ return { jsonrpc: "2.0", id: req.id, result };
1702
+ } catch (err) {
1703
+ return {
1704
+ jsonrpc: "2.0",
1705
+ id: req.id,
1706
+ error: { code: -32e3, message: err.message }
1707
+ };
1708
+ }
1709
+ }
1710
+ function createIpcServer(socketPath) {
1711
+ let server = null;
1712
+ const connections = /* @__PURE__ */ new Set();
1713
+ function handleConnection(socket) {
1714
+ connections.add(socket);
1715
+ let buffer = "";
1716
+ socket.on("data", async (data) => {
1717
+ buffer += data.toString();
1718
+ const { messages, remainder } = parseMessages(buffer);
1719
+ buffer = remainder;
1720
+ for (const msg of messages) {
1721
+ if ("method" in msg) {
1722
+ const response = await handleRequest(msg);
1723
+ try {
1724
+ socket.write(serializeMessage(response));
1725
+ } catch {
1726
+ }
1727
+ }
1728
+ }
1729
+ });
1730
+ socket.on("close", () => {
1731
+ connections.delete(socket);
1732
+ });
1733
+ socket.on("error", () => {
1734
+ connections.delete(socket);
1735
+ });
1736
+ }
1737
+ async function cleanStaleSocket() {
1738
+ if (!existsSync5(socketPath)) return;
1739
+ return new Promise((resolve3) => {
1740
+ const probe = net.createConnection(socketPath);
1741
+ probe.on("connect", () => {
1742
+ probe.destroy();
1743
+ resolve3();
1744
+ });
1745
+ probe.on("error", () => {
1746
+ try {
1747
+ unlinkSync(socketPath);
1748
+ } catch {
1749
+ }
1750
+ resolve3();
1751
+ });
1752
+ });
1753
+ }
1754
+ return {
1755
+ async start() {
1756
+ mkdirSync(dirname4(socketPath), { recursive: true });
1757
+ await cleanStaleSocket();
1758
+ return new Promise((resolve3, reject) => {
1759
+ server = net.createServer(handleConnection);
1760
+ server.on("error", (err) => {
1761
+ if (err.code === "EADDRINUSE") {
1762
+ try {
1763
+ unlinkSync(socketPath);
1764
+ } catch {
1765
+ }
1766
+ server.listen(socketPath, () => resolve3());
1767
+ } else {
1768
+ reject(err);
1769
+ }
1770
+ });
1771
+ server.listen(socketPath, () => resolve3());
1772
+ });
1773
+ },
1774
+ async stop() {
1775
+ for (const conn of connections) {
1776
+ conn.destroy();
1777
+ }
1778
+ connections.clear();
1779
+ return new Promise((resolve3) => {
1780
+ if (!server) {
1781
+ resolve3();
1782
+ return;
1783
+ }
1784
+ server.close(() => {
1785
+ try {
1786
+ unlinkSync(socketPath);
1787
+ } catch {
1788
+ }
1789
+ server = null;
1790
+ resolve3();
1791
+ });
1792
+ });
1793
+ }
1794
+ };
1795
+ }
1539
1796
 
1540
1797
  // src/pipeline/engine.ts
1541
1798
  async function executePipeline(pipeline, onProgress, cwd = process.cwd()) {
@@ -1590,32 +1847,8 @@ async function executePipeline(pipeline, onProgress, cwd = process.cwd()) {
1590
1847
  }
1591
1848
 
1592
1849
  // src/config/projectConfig.ts
1593
- import { existsSync as existsSync5, readFileSync as readFileSync2, writeFileSync, mkdirSync } from "fs";
1594
- import { join as join5 } from "path";
1595
-
1596
- // src/lib/packageRoot.ts
1597
- import { existsSync as existsSync4 } from "fs";
1598
- import { dirname as dirname3, join as join4, resolve as resolve2 } from "path";
1599
- var rootCache = /* @__PURE__ */ new Map();
1600
- function findNearestPackageRoot(startDir = process.cwd()) {
1601
- const resolvedStart = resolve2(startDir);
1602
- if (rootCache.has(resolvedStart)) return rootCache.get(resolvedStart);
1603
- let currentDir = resolvedStart;
1604
- while (true) {
1605
- if (existsSync4(join4(currentDir, "package.json"))) {
1606
- rootCache.set(resolvedStart, currentDir);
1607
- return currentDir;
1608
- }
1609
- const parentDir = dirname3(currentDir);
1610
- if (parentDir === currentDir) {
1611
- rootCache.set(resolvedStart, void 0);
1612
- return void 0;
1613
- }
1614
- currentDir = parentDir;
1615
- }
1616
- }
1617
-
1618
- // src/config/projectConfig.ts
1850
+ import { existsSync as existsSync6, readFileSync as readFileSync2, writeFileSync, mkdirSync as mkdirSync2 } from "fs";
1851
+ import { join as join6 } from "path";
1619
1852
  var CONFIG_DIR = ".polter";
1620
1853
  var CONFIG_FILE = "config.json";
1621
1854
  function defaultConfig() {
@@ -1628,13 +1861,13 @@ function defaultConfig() {
1628
1861
  function getProjectConfigPath(startDir) {
1629
1862
  const root = findNearestPackageRoot(startDir);
1630
1863
  if (!root) return void 0;
1631
- const dir = join5(root, CONFIG_DIR);
1632
- return { dir, file: join5(dir, CONFIG_FILE) };
1864
+ const dir = join6(root, CONFIG_DIR);
1865
+ return { dir, file: join6(dir, CONFIG_FILE) };
1633
1866
  }
1634
1867
  function readProjectConfig(startDir) {
1635
1868
  const paths = getProjectConfigPath(startDir);
1636
1869
  if (!paths) return void 0;
1637
- if (!existsSync5(paths.file)) return void 0;
1870
+ if (!existsSync6(paths.file)) return void 0;
1638
1871
  try {
1639
1872
  const raw = readFileSync2(paths.file, "utf-8");
1640
1873
  return JSON.parse(raw);
@@ -1645,7 +1878,7 @@ function readProjectConfig(startDir) {
1645
1878
  function writeProjectConfig(config2, startDir) {
1646
1879
  const paths = getProjectConfigPath(startDir);
1647
1880
  if (!paths) return false;
1648
- mkdirSync(paths.dir, { recursive: true });
1881
+ mkdirSync2(paths.dir, { recursive: true });
1649
1882
  writeFileSync(paths.file, JSON.stringify(config2, null, 2) + "\n", "utf-8");
1650
1883
  return true;
1651
1884
  }
@@ -1735,8 +1968,8 @@ function findPipelineByName(name, startDir) {
1735
1968
  }
1736
1969
 
1737
1970
  // src/declarative/parser.ts
1738
- import { existsSync as existsSync6, readFileSync as readFileSync3 } from "fs";
1739
- import { join as join6 } from "path";
1971
+ import { existsSync as existsSync7, readFileSync as readFileSync3 } from "fs";
1972
+ import { join as join7 } from "path";
1740
1973
  var YAML_FILE = "polter.yaml";
1741
1974
  function parseSimpleYaml(content) {
1742
1975
  const lines = content.split("\n");
@@ -1808,8 +2041,8 @@ function parseValue(raw) {
1808
2041
  return raw;
1809
2042
  }
1810
2043
  function findPolterYaml(startDir = process.cwd()) {
1811
- const filePath = join6(startDir, YAML_FILE);
1812
- return existsSync6(filePath) ? filePath : void 0;
2044
+ const filePath = join7(startDir, YAML_FILE);
2045
+ return existsSync7(filePath) ? filePath : void 0;
1813
2046
  }
1814
2047
  function parsePolterYaml(startDir = process.cwd()) {
1815
2048
  const filePath = findPolterYaml(startDir);
@@ -1955,16 +2188,16 @@ async function applyActions(actions, cwd = process.cwd(), onProgress) {
1955
2188
 
1956
2189
  // src/lib/mcpInstaller.ts
1957
2190
  import { spawnSync as spawnSync2 } from "child_process";
1958
- import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, existsSync as existsSync7 } from "fs";
1959
- import { join as join7, dirname as dirname4 } from "path";
2191
+ import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3, existsSync as existsSync8 } from "fs";
2192
+ import { join as join8, dirname as dirname5 } from "path";
1960
2193
  import { fileURLToPath } from "url";
1961
2194
  import { homedir } from "os";
1962
2195
  import pc from "picocolors";
1963
- var __dirname = dirname4(fileURLToPath(import.meta.url));
2196
+ var __dirname = dirname5(fileURLToPath(import.meta.url));
1964
2197
  function readPkgVersion() {
1965
2198
  for (const rel of ["../../package.json", "../package.json"]) {
1966
- const p = join7(__dirname, rel);
1967
- if (existsSync7(p)) {
2199
+ const p = join8(__dirname, rel);
2200
+ if (existsSync8(p)) {
1968
2201
  const pkg = JSON.parse(readFileSync4(p, "utf-8"));
1969
2202
  return pkg.version;
1970
2203
  }
@@ -1987,15 +2220,15 @@ function tryClaudeCli(scope) {
1987
2220
  }
1988
2221
  function getSettingsPath(scope) {
1989
2222
  if (scope === "project") {
1990
- return join7(process.cwd(), ".mcp.json");
2223
+ return join8(process.cwd(), ".mcp.json");
1991
2224
  }
1992
- return join7(homedir(), ".claude", "settings.json");
2225
+ return join8(homedir(), ".claude", "settings.json");
1993
2226
  }
1994
2227
  function tryManualInstall(scope) {
1995
2228
  const settingsPath = getSettingsPath(scope);
1996
- const dir = join7(settingsPath, "..");
2229
+ const dir = join8(settingsPath, "..");
1997
2230
  let settings = {};
1998
- if (existsSync7(settingsPath)) {
2231
+ if (existsSync8(settingsPath)) {
1999
2232
  try {
2000
2233
  settings = JSON.parse(readFileSync4(settingsPath, "utf-8"));
2001
2234
  } catch {
@@ -2004,7 +2237,7 @@ function tryManualInstall(scope) {
2004
2237
  return false;
2005
2238
  }
2006
2239
  } else {
2007
- mkdirSync2(dir, { recursive: true });
2240
+ mkdirSync3(dir, { recursive: true });
2008
2241
  }
2009
2242
  const mcpServers = settings.mcpServers ?? {};
2010
2243
  mcpServers.polter = {
@@ -2056,7 +2289,7 @@ async function removeMcpServer(scope) {
2056
2289
  process.stdout.write(pc.yellow(" 'claude mcp remove' failed, falling back to manual removal...\n\n"));
2057
2290
  }
2058
2291
  const settingsPath = getSettingsPath(scope);
2059
- if (!existsSync7(settingsPath)) {
2292
+ if (!existsSync8(settingsPath)) {
2060
2293
  process.stdout.write(pc.yellow(" No settings file found. Nothing to remove.\n"));
2061
2294
  return;
2062
2295
  }
@@ -2082,11 +2315,11 @@ async function removeMcpServer(scope) {
2082
2315
  function getMcpStatusInfo() {
2083
2316
  const version = readPkgVersion();
2084
2317
  const scopeDefs = [
2085
- { label: "Project (.mcp.json)", path: join7(process.cwd(), ".mcp.json"), scope: "project" },
2086
- { label: "User (~/.claude/settings.json)", path: join7(homedir(), ".claude", "settings.json"), scope: "user" }
2318
+ { label: "Project (.mcp.json)", path: join8(process.cwd(), ".mcp.json"), scope: "project" },
2319
+ { label: "User (~/.claude/settings.json)", path: join8(homedir(), ".claude", "settings.json"), scope: "user" }
2087
2320
  ];
2088
2321
  const scopes = scopeDefs.map((s) => {
2089
- if (!existsSync7(s.path)) {
2322
+ if (!existsSync8(s.path)) {
2090
2323
  return { label: s.label, scope: s.scope, registered: false };
2091
2324
  }
2092
2325
  try {
@@ -2133,7 +2366,7 @@ async function removeMcpServerSilent(scope) {
2133
2366
  messages.push("'claude mcp remove' failed, falling back to manual removal...");
2134
2367
  }
2135
2368
  const settingsPath = getSettingsPath(scope);
2136
- if (!existsSync7(settingsPath)) {
2369
+ if (!existsSync8(settingsPath)) {
2137
2370
  messages.push("No settings file found. Nothing to remove.");
2138
2371
  return { success: true, message: messages.join("\n") };
2139
2372
  }
@@ -2172,11 +2405,11 @@ async function mcpStatus() {
2172
2405
  }
2173
2406
  process.stdout.write("\n");
2174
2407
  const scopes = [
2175
- { label: "Project (.mcp.json)", path: join7(process.cwd(), ".mcp.json"), key: "project" },
2176
- { label: "User (~/.claude/settings.json)", path: join7(homedir(), ".claude", "settings.json"), key: "user" }
2408
+ { label: "Project (.mcp.json)", path: join8(process.cwd(), ".mcp.json"), key: "project" },
2409
+ { label: "User (~/.claude/settings.json)", path: join8(homedir(), ".claude", "settings.json"), key: "user" }
2177
2410
  ];
2178
2411
  for (const scope of scopes) {
2179
- if (!existsSync7(scope.path)) {
2412
+ if (!existsSync8(scope.path)) {
2180
2413
  process.stdout.write(` ${scope.label}: ${pc.dim("not found")}
2181
2414
  `);
2182
2415
  continue;
@@ -2198,6 +2431,119 @@ async function mcpStatus() {
2198
2431
  }
2199
2432
  }
2200
2433
 
2434
+ // src/lib/skillSetup.ts
2435
+ import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, mkdirSync as mkdirSync4, existsSync as existsSync9 } from "fs";
2436
+ import { join as join9 } from "path";
2437
+ import { homedir as homedir2 } from "os";
2438
+ import pc2 from "picocolors";
2439
+ var SKILL_DIR = join9(homedir2(), ".claude", "skills", "polter");
2440
+ var SKILL_PATH = join9(SKILL_DIR, "SKILL.md");
2441
+ var SKILL_CONTENT = `---
2442
+ name: polter
2443
+ description: "Polter - Infrastructure Orchestrator. Use when developing in any project to: monitor dev processes and check logs for errors after code changes, manage pipelines (multi-step command sequences), run CLI commands (Supabase, GitHub, Vercel, Git), manage packages (install, build, publish, audit), and apply declarative infrastructure from polter.yaml."
2444
+ ---
2445
+
2446
+ # Polter Skill
2447
+
2448
+ You have access to Polter MCP tools for infrastructure orchestration. Use them proactively during development.
2449
+
2450
+ ## Process Monitoring
2451
+
2452
+ **Tools:** \`polter_ps\`, \`polter_logs\`, \`polter_start\`, \`polter_stop\`, \`polter_find_process\`, \`polter_smart_start\`, \`polter_run_script_bg\`
2453
+
2454
+ - At the start of a session, run \`polter_ps\` to check for active dev processes
2455
+ - After significant code edits, check \`polter_logs\` for compilation or runtime errors
2456
+ - Use \`polter_find_process\` to find processes running in the current directory
2457
+ - Use \`polter_smart_start\` to start package.json scripts as background processes (e.g. dev servers)
2458
+ - Use \`polter_run_script_bg\` to run arbitrary scripts in the background
2459
+ - Use \`polter_stop\` to stop processes that are no longer needed
2460
+
2461
+ ## CLI Commands
2462
+
2463
+ **Tools:** \`polter_list_commands\`, \`polter_run_command\`, \`polter_status\`
2464
+
2465
+ - Execute commands for Supabase, GitHub CLI, Vercel, and Git via their command IDs
2466
+ - Use \`polter_list_commands\` to discover available commands, optionally filtered by tool
2467
+ - Use \`polter_run_command\` to execute a command by its ID with additional args/flags
2468
+ - Check \`polter_status\` to see which CLI tools are installed and their versions
2469
+
2470
+ ## Pipelines
2471
+
2472
+ **Tools:** \`polter_list_pipelines\`, \`polter_run_pipeline\`, \`polter_create_pipeline\`, \`polter_update_pipeline\`, \`polter_delete_pipeline\`
2473
+
2474
+ - List and run saved multi-step command sequences with \`polter_list_pipelines\` and \`polter_run_pipeline\`
2475
+ - Create new pipelines for repetitive workflows (e.g. build + test + deploy) with \`polter_create_pipeline\`
2476
+ - Suggest creating pipelines when you notice the user repeating the same sequence of commands
2477
+
2478
+ ## Package Management
2479
+
2480
+ **Tools:** \`polter_pkg_build\`, \`polter_pkg_install\`, \`polter_pkg_publish\`, \`polter_pkg_run_script\`, \`polter_pkg_version_bump\`, \`polter_pkg_audit\`, \`polter_pkg_info\`
2481
+
2482
+ - Auto-detects the package manager (npm, pnpm, yarn, bun) from lockfiles
2483
+ - Use \`polter_pkg_build\` for building, \`polter_pkg_install\` for installing dependencies
2484
+ - Use \`polter_pkg_run_script\` to run package.json scripts
2485
+ - Use \`polter_pkg_audit\` to check for vulnerabilities
2486
+ - Use \`polter_pkg_version_bump\` before publishing, then \`polter_pkg_publish\`
2487
+
2488
+ ## Declarative Infrastructure
2489
+
2490
+ **Tools:** \`polter_plan\`, \`polter_apply\`
2491
+
2492
+ - Use \`polter_plan\` to read \`polter.yaml\` and compute a diff of desired vs current state
2493
+ - Use \`polter_apply\` to execute the planned infrastructure changes
2494
+ - Always run \`polter_plan\` first to review changes before applying
2495
+
2496
+ ## Workflow Recommendations
2497
+
2498
+ 1. **Starting a session:** Run \`polter_ps\` to see what's already running
2499
+ 2. **After code changes:** Check \`polter_logs\` for errors in dev server output
2500
+ 3. **Setting up a project:** Use \`polter_status\` to verify tools, then \`polter_smart_start\` for dev server
2501
+ 4. **Deploying:** Create a pipeline with build + test + deploy steps
2502
+ 5. **Infrastructure changes:** Edit \`polter.yaml\`, run \`polter_plan\`, then \`polter_apply\`
2503
+ `;
2504
+ function setupSkill() {
2505
+ if (existsSync9(SKILL_PATH)) {
2506
+ const existing = readFileSync5(SKILL_PATH, "utf-8");
2507
+ if (existing === SKILL_CONTENT) {
2508
+ return { status: "already-up-to-date", path: SKILL_PATH };
2509
+ }
2510
+ writeFileSync3(SKILL_PATH, SKILL_CONTENT, "utf-8");
2511
+ return { status: "updated", path: SKILL_PATH };
2512
+ }
2513
+ mkdirSync4(SKILL_DIR, { recursive: true });
2514
+ writeFileSync3(SKILL_PATH, SKILL_CONTENT, "utf-8");
2515
+ return { status: "created", path: SKILL_PATH };
2516
+ }
2517
+ function setupSkillCli() {
2518
+ const result = setupSkill();
2519
+ switch (result.status) {
2520
+ case "created":
2521
+ process.stdout.write(pc2.green(`
2522
+ Skill installed at ${result.path}
2523
+ `));
2524
+ process.stdout.write(pc2.dim(" Use /polter in Claude Code to activate.\n\n"));
2525
+ break;
2526
+ case "updated":
2527
+ process.stdout.write(pc2.green(`
2528
+ Skill updated at ${result.path}
2529
+ `));
2530
+ process.stdout.write(pc2.dim(" Use /polter in Claude Code to activate.\n\n"));
2531
+ break;
2532
+ case "already-up-to-date":
2533
+ process.stdout.write(pc2.cyan(`
2534
+ Skill already up to date at ${result.path}
2535
+
2536
+ `));
2537
+ break;
2538
+ }
2539
+ }
2540
+ function getSkillContent() {
2541
+ return SKILL_CONTENT;
2542
+ }
2543
+ function getSkillPath() {
2544
+ return SKILL_PATH;
2545
+ }
2546
+
2201
2547
  export {
2202
2548
  __export,
2203
2549
  allCommands,
@@ -2220,8 +2566,10 @@ export {
2220
2566
  resolveToolCommand,
2221
2567
  getToolInfo,
2222
2568
  getToolLinkInfo,
2569
+ findNearestPackageRoot,
2223
2570
  generateProcessId,
2224
2571
  startProcess,
2572
+ registerForegroundProcess,
2225
2573
  stopProcess,
2226
2574
  listProcesses,
2227
2575
  getProcessOutput,
@@ -2229,8 +2577,11 @@ export {
2229
2577
  removeProcess,
2230
2578
  findProcessesByCwd,
2231
2579
  findRunningByCommand,
2580
+ getSocketPath,
2581
+ serializeMessage,
2582
+ parseMessages,
2583
+ createIpcServer,
2232
2584
  executePipeline,
2233
- findNearestPackageRoot,
2234
2585
  getProjectConfigPath,
2235
2586
  writeProjectConfig,
2236
2587
  getOrCreateProjectConfig,
@@ -2248,5 +2599,9 @@ export {
2248
2599
  getMcpStatusInfo,
2249
2600
  installMcpServerSilent,
2250
2601
  removeMcpServerSilent,
2251
- mcpStatus
2602
+ mcpStatus,
2603
+ setupSkill,
2604
+ setupSkillCli,
2605
+ getSkillContent,
2606
+ getSkillPath
2252
2607
  };