@uniformdev/cli 20.40.0 → 20.42.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.
Files changed (2) hide show
  1. package/dist/index.mjs +138 -26
  2. package/package.json +9 -9
package/dist/index.mjs CHANGED
@@ -1095,7 +1095,7 @@ import { PostHog } from "posthog-node";
1095
1095
  // package.json
1096
1096
  var package_default = {
1097
1097
  name: "@uniformdev/cli",
1098
- version: "20.40.0",
1098
+ version: "20.42.0",
1099
1099
  description: "Uniform command line interface tool",
1100
1100
  license: "SEE LICENSE IN LICENSE.txt",
1101
1101
  main: "./cli.js",
@@ -1245,6 +1245,7 @@ async function selectAgent(agentOption, options = {}) {
1245
1245
  choices: [
1246
1246
  { name: "Cursor", value: "cursor" },
1247
1247
  { name: "Claude Desktop", value: "claude" },
1248
+ { name: "GitHub Copilot (VS Code)", value: "copilot" },
1248
1249
  { name: "Other AI assistant", value: "other" }
1249
1250
  ]
1250
1251
  }
@@ -1267,6 +1268,12 @@ function getRulesDirectory(agentType, customDir) {
1267
1268
  agentType,
1268
1269
  isCustom: false
1269
1270
  };
1271
+ case "copilot":
1272
+ return {
1273
+ path: path2.join(currentDir, ".github", "instructions"),
1274
+ agentType,
1275
+ isCustom: false
1276
+ };
1270
1277
  case "claude":
1271
1278
  case "other":
1272
1279
  default:
@@ -1292,6 +1299,12 @@ function getMcpDirectory(agentType, customDir) {
1292
1299
  agentType,
1293
1300
  isCustom: false
1294
1301
  };
1302
+ case "copilot":
1303
+ return {
1304
+ path: path2.join(process.cwd(), ".vscode"),
1305
+ agentType,
1306
+ isCustom: false
1307
+ };
1295
1308
  case "claude":
1296
1309
  case "other":
1297
1310
  default:
@@ -1319,7 +1332,7 @@ function createUniformMcpServerConfig(apiKey, projectId, aiApiHost, apiHost) {
1319
1332
  }
1320
1333
  };
1321
1334
  }
1322
- function readOrCreateMcpConfig(mcpConfigPath) {
1335
+ function readOrCreateMcpConfig(mcpConfigPath, agentType) {
1323
1336
  if (existsSync3(mcpConfigPath)) {
1324
1337
  try {
1325
1338
  const existingConfig = readFileSync(mcpConfigPath, "utf8");
@@ -1331,19 +1344,39 @@ function readOrCreateMcpConfig(mcpConfigPath) {
1331
1344
  Error: ${error}`
1332
1345
  )
1333
1346
  );
1334
- return { mcpServers: {} };
1347
+ return agentType === "copilot" ? { servers: {} } : { mcpServers: {} };
1335
1348
  }
1336
1349
  }
1337
- return { mcpServers: {} };
1350
+ return agentType === "copilot" ? { servers: {} } : { mcpServers: {} };
1338
1351
  }
1339
- function mergeMcpConfig(existingConfig, uniformServer) {
1340
- return {
1341
- ...existingConfig,
1342
- mcpServers: {
1343
- ...existingConfig.mcpServers,
1344
- Uniform: uniformServer
1345
- }
1346
- };
1352
+ function mergeMcpConfig(existingConfig, uniformServer, agentType) {
1353
+ if (agentType === "copilot") {
1354
+ const copilotConfig = existingConfig;
1355
+ return {
1356
+ ...copilotConfig,
1357
+ servers: {
1358
+ ...copilotConfig.servers,
1359
+ Uniform: uniformServer
1360
+ }
1361
+ };
1362
+ } else {
1363
+ const standardConfig = existingConfig;
1364
+ return {
1365
+ ...standardConfig,
1366
+ mcpServers: {
1367
+ ...standardConfig.mcpServers,
1368
+ Uniform: uniformServer
1369
+ }
1370
+ };
1371
+ }
1372
+ }
1373
+ function getExistingServers(config2) {
1374
+ if ("servers" in config2) {
1375
+ return config2.servers || {};
1376
+ } else if ("mcpServers" in config2) {
1377
+ return config2.mcpServers || {};
1378
+ }
1379
+ return {};
1347
1380
  }
1348
1381
 
1349
1382
  // src/commands/ai/commands/mcp/install.ts
@@ -1356,9 +1389,9 @@ var InstallMcpCommand = {
1356
1389
  builder: (yargs41) => withConfiguration(
1357
1390
  yargs41.option("agent", {
1358
1391
  alias: "a",
1359
- describe: "Specify agent type (cursor, claude, other)",
1392
+ describe: "Specify agent type (cursor, claude, copilot, other)",
1360
1393
  type: "string",
1361
- choices: ["cursor", "claude", "other"]
1394
+ choices: ["cursor", "claude", "copilot", "other"]
1362
1395
  }).option("directory", {
1363
1396
  alias: "d",
1364
1397
  describe: "Custom installation directory for MCP configuration (.mcp.json for Claude, mcp.json for others)",
@@ -1464,21 +1497,31 @@ Selected agent: ${agentType}`));
1464
1497
  let done = await spin("Creating directory if needed...");
1465
1498
  await ensureDirectoryExists(mcpDirectory);
1466
1499
  await done();
1467
- const mcpConfigPath = join3(mcpDirectory, agentType === "claude" ? ".mcp.json" : "mcp.json");
1500
+ let mcpConfigFileName;
1501
+ if (agentType === "claude") {
1502
+ mcpConfigFileName = ".mcp.json";
1503
+ } else if (agentType === "copilot") {
1504
+ mcpConfigFileName = "mcp.json";
1505
+ } else {
1506
+ mcpConfigFileName = "mcp.json";
1507
+ }
1508
+ const mcpConfigPath = join3(mcpDirectory, mcpConfigFileName);
1468
1509
  done = await spin("Reading existing MCP configuration...");
1469
- const existingConfig = readOrCreateMcpConfig(mcpConfigPath);
1510
+ const existingConfig = readOrCreateMcpConfig(mcpConfigPath, agentType);
1470
1511
  await done();
1471
1512
  const uniformServer = createUniformMcpServerConfig(writeApiKey, projectId, aiApiHost, apiHost);
1472
- const mergedConfig = mergeMcpConfig(existingConfig, uniformServer);
1513
+ const mergedConfig = mergeMcpConfig(existingConfig, uniformServer, agentType);
1473
1514
  done = await spin("Updating MCP configuration...");
1474
1515
  writeFileSync(mcpConfigPath, JSON.stringify(mergedConfig, null, 2));
1475
1516
  await done();
1476
- const hasExistingServers = Object.keys(existingConfig.mcpServers || {}).length > 0;
1517
+ const existingServers = getExistingServers(existingConfig);
1518
+ const hasExistingServers = Object.keys(existingServers).length > 0;
1477
1519
  const actionText = hasExistingServers ? "updated" : "created";
1478
1520
  console.log(green2(`\u2705 MCP configuration ${actionText} successfully!
1479
1521
  `));
1480
1522
  if (hasExistingServers) {
1481
- const otherServers = Object.keys(mergedConfig.mcpServers).filter((key) => key !== "Uniform");
1523
+ const mergedServers = getExistingServers(mergedConfig);
1524
+ const otherServers = Object.keys(mergedServers).filter((key) => key !== "Uniform");
1482
1525
  if (otherServers.length > 0) {
1483
1526
  console.log(green2(`\u{1F4CB} Preserved existing MCP servers: ${otherServers.join(", ")}`));
1484
1527
  }
@@ -1504,6 +1547,11 @@ Selected agent: ${agentType}`));
1504
1547
  console.log(`2. Configuration saved to: ${mcpConfigPath}`);
1505
1548
  console.log("3. The Uniform MCP server will be available in Claude's interface");
1506
1549
  console.log("4. Check via /mcp command in Claude code");
1550
+ } else if (agentType === "copilot") {
1551
+ console.log(blue("\n\u{1F4CB} Next steps for GitHub Copilot (VS Code):"));
1552
+ console.log("1. Restart VS Code to load the new MCP configuration");
1553
+ console.log(`2. Configuration saved to: ${mcpConfigPath}`);
1554
+ console.log("3. The Uniform MCP server will be available in GitHub Copilot's AI chat");
1507
1555
  } else {
1508
1556
  console.log(yellow3("\n\u{1F4CB} Next steps:"));
1509
1557
  console.log("1. Register MCP server in your assistant per documentation");
@@ -1775,14 +1823,57 @@ async function installRules(options = {}, spin) {
1775
1823
  console.log(green3(`\u{1F3AF} Detected: ${getFrameworkDescription(frameworkDetection)}`));
1776
1824
  }
1777
1825
  const agentType = await selectAgent(options.agent);
1826
+ let installLocation;
1827
+ if (agentType === "copilot") {
1828
+ const { location } = await inquirer5.prompt([
1829
+ {
1830
+ type: "list",
1831
+ name: "location",
1832
+ message: "Where would you like to install the instructions?",
1833
+ choices: [
1834
+ {
1835
+ name: "Workspace (.github/instructions) - Available only in this workspace",
1836
+ value: "workspace"
1837
+ },
1838
+ {
1839
+ name: "User profile - Available across all workspaces (requires VS Code profile setup)",
1840
+ value: "user"
1841
+ }
1842
+ ],
1843
+ default: "workspace"
1844
+ }
1845
+ ]);
1846
+ installLocation = location;
1847
+ }
1778
1848
  const selectedRules = await selectRules(availableRules, frameworkDetection);
1779
1849
  if (selectedRules.length === 0) {
1780
1850
  console.log(yellow4("No rules selected. Exiting..."));
1781
1851
  return;
1782
1852
  }
1783
- const directoryConfig = getRulesDirectory(agentType, options.directory);
1853
+ let directoryConfig = getRulesDirectory(agentType, options.directory);
1854
+ if (agentType === "copilot") {
1855
+ if (installLocation === "workspace") {
1856
+ directoryConfig = {
1857
+ path: path4.join(process.cwd(), ".github", "instructions"),
1858
+ agentType,
1859
+ isCustom: false
1860
+ };
1861
+ console.log(yellow4(`
1862
+ \u{1F4C1} Installing to workspace instructions: ${directoryConfig.path}`));
1863
+ } else if (installLocation === "user") {
1864
+ console.log(yellow4("\n\u26A0\uFE0F Note: User profile installation requires manual setup."));
1865
+ console.log(
1866
+ yellow4("Files will be saved to current directory for you to copy to your VS Code profile.")
1867
+ );
1868
+ directoryConfig = {
1869
+ path: path4.join(process.cwd(), "copilot-instructions"),
1870
+ agentType,
1871
+ isCustom: false
1872
+ };
1873
+ }
1874
+ }
1784
1875
  const installDir = directoryConfig.path;
1785
- await installSelectedRules(selectedRules, installDir, spin);
1876
+ await installSelectedRules(selectedRules, installDir, agentType, spin);
1786
1877
  showSuccessMessage(agentType, installDir, selectedRules);
1787
1878
  } catch (error) {
1788
1879
  if (done) {
@@ -1902,7 +1993,7 @@ function getCategoryDisplayName(category) {
1902
1993
  };
1903
1994
  return displayNames[category] || category.charAt(0).toUpperCase() + category.slice(1);
1904
1995
  }
1905
- async function installSelectedRules(selectedRules, installDir, spin) {
1996
+ async function installSelectedRules(selectedRules, installDir, agentType, spin) {
1906
1997
  let done;
1907
1998
  if (spin) {
1908
1999
  done = await spin(`Installing ${selectedRules.length} rules...`);
@@ -1911,8 +2002,13 @@ async function installSelectedRules(selectedRules, installDir, spin) {
1911
2002
  await ensureDirectoryExists(installDir);
1912
2003
  for (const rule of selectedRules) {
1913
2004
  const content = await downloadFileContent(rule.path);
1914
- const filePath = path4.join(installDir, rule.name);
1915
- await fs6.writeFile(filePath, content, "utf8");
2005
+ let fileName = rule.name;
2006
+ const fileContent = content;
2007
+ if (agentType === "copilot") {
2008
+ fileName = rule.name.replace(/\.(md|txt)$/, ".instructions.md");
2009
+ }
2010
+ const filePath = path4.join(installDir, fileName);
2011
+ await fs6.writeFile(filePath, fileContent, "utf8");
1916
2012
  }
1917
2013
  if (done) {
1918
2014
  await done();
@@ -1944,6 +2040,22 @@ function showSuccessMessage(agentType, installDir, selectedRules) {
1944
2040
  console.log("1. Point Claude Code to the rules folder to augment its understanding");
1945
2041
  console.log("2. Use the rules in your development context");
1946
2042
  break;
2043
+ case "copilot":
2044
+ console.log(blue2("For GitHub Copilot (VS Code):"));
2045
+ if (installDir.includes("copilot-instructions")) {
2046
+ console.log("1. Copy the generated .instructions.md files to your VS Code profile:");
2047
+ console.log(" \u2022 Open VS Code Command Palette (Cmd/Ctrl+Shift+P)");
2048
+ console.log(' \u2022 Run "Preferences: Open User Settings (JSON)"');
2049
+ console.log(" \u2022 Locate your VS Code profile directory");
2050
+ console.log(" \u2022 Copy files from the copilot-instructions folder to your profile");
2051
+ } else {
2052
+ console.log("1. The instructions files are now in your .github/instructions folder");
2053
+ console.log("2. Restart VS Code to reload the instruction files");
2054
+ console.log("3. Instructions will be automatically applied based on file patterns");
2055
+ }
2056
+ console.log('4. Use "Add Context > Instructions" in Copilot Chat for specific rules');
2057
+ console.log('5. Instructions use YAML frontmatter with "applyTo" patterns');
2058
+ break;
1947
2059
  default:
1948
2060
  console.log(blue2("For your AI assistant:"));
1949
2061
  console.log("1. Point your AI tool to the rules folder");
@@ -1961,9 +2073,9 @@ var InstallRulesCommand = {
1961
2073
  builder: (yargs41) => withConfiguration(
1962
2074
  yargs41.option("agent", {
1963
2075
  alias: "a",
1964
- describe: "Specify agent type (cursor, claude, other)",
2076
+ describe: "Specify agent type (cursor, claude, copilot, other)",
1965
2077
  type: "string",
1966
- choices: ["cursor", "claude", "other"]
2078
+ choices: ["cursor", "claude", "copilot", "other"]
1967
2079
  }).option("directory", {
1968
2080
  alias: "d",
1969
2081
  describe: "Custom installation directory (also used for framework detection)",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uniformdev/cli",
3
- "version": "20.40.0",
3
+ "version": "20.42.0",
4
4
  "description": "Uniform command line interface tool",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "main": "./cli.js",
@@ -27,13 +27,13 @@
27
27
  },
28
28
  "dependencies": {
29
29
  "@thi.ng/mime": "^2.2.23",
30
- "@uniformdev/assets": "20.40.0",
31
- "@uniformdev/canvas": "20.40.0",
32
- "@uniformdev/context": "20.40.0",
33
- "@uniformdev/files": "20.40.0",
34
- "@uniformdev/project-map": "20.40.0",
35
- "@uniformdev/redirect": "20.40.0",
36
- "@uniformdev/richtext": "20.40.0",
30
+ "@uniformdev/assets": "20.42.0",
31
+ "@uniformdev/canvas": "20.42.0",
32
+ "@uniformdev/context": "20.42.0",
33
+ "@uniformdev/files": "20.42.0",
34
+ "@uniformdev/project-map": "20.42.0",
35
+ "@uniformdev/redirect": "20.42.0",
36
+ "@uniformdev/richtext": "20.42.0",
37
37
  "call-bind": "^1.0.2",
38
38
  "colorette": "2.0.20",
39
39
  "cosmiconfig": "9.0.0",
@@ -82,5 +82,5 @@
82
82
  "publishConfig": {
83
83
  "access": "public"
84
84
  },
85
- "gitHead": "5a63373f91355d8865feac0d3fc11be59a5e38bd"
85
+ "gitHead": "2002a4f5112b8796179d6d9fae5df26a45f8ea1d"
86
86
  }