@omnidev-ai/cli 0.7.0 → 0.8.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.js +131 -79
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -32,26 +32,24 @@ import { existsSync as existsSync4 } from "node:fs";
32
32
 
33
33
  // ../adapters/src/claude-code/index.ts
34
34
  import { existsSync, mkdirSync } from "node:fs";
35
- import { writeFile } from "node:fs/promises";
35
+ import { readFile, writeFile } from "node:fs/promises";
36
36
  import { join } from "node:path";
37
37
  var claudeCodeAdapter = {
38
38
  id: "claude-code",
39
39
  displayName: "Claude Code",
40
- async init(ctx) {
41
- const claudeMdPath = join(ctx.projectRoot, "CLAUDE.md");
42
- const filesCreated = [];
43
- if (!existsSync(claudeMdPath)) {
44
- await writeFile(claudeMdPath, generateClaudeTemplate(), "utf-8");
45
- filesCreated.push("CLAUDE.md");
46
- }
40
+ async init(_ctx) {
47
41
  return {
48
- filesCreated,
49
- message: filesCreated.length > 0 ? `Created ${filesCreated.join(", ")}` : "CLAUDE.md already exists"
42
+ filesCreated: [],
43
+ message: "Claude Code adapter initialized"
50
44
  };
51
45
  },
52
46
  async sync(bundle, ctx) {
53
47
  const filesWritten = [];
54
48
  const filesDeleted = [];
49
+ const claudeMdPath = join(ctx.projectRoot, "CLAUDE.md");
50
+ const claudeMdContent = await generateClaudeMdContent(ctx.projectRoot);
51
+ await writeFile(claudeMdPath, claudeMdContent, "utf-8");
52
+ filesWritten.push("CLAUDE.md");
55
53
  const skillsDir = join(ctx.projectRoot, ".claude", "skills");
56
54
  mkdirSync(skillsDir, { recursive: true });
57
55
  for (const skill of bundle.skills) {
@@ -73,51 +71,61 @@ ${skill.instructions}`;
73
71
  };
74
72
  }
75
73
  };
76
- function generateClaudeTemplate() {
77
- return `# Project Instructions
78
-
79
- <!-- Add your project-specific instructions here -->
74
+ async function generateClaudeMdContent(projectRoot) {
75
+ const omniMdPath = join(projectRoot, "OMNI.md");
76
+ let omniMdContent = "";
77
+ if (existsSync(omniMdPath)) {
78
+ omniMdContent = await readFile(omniMdPath, "utf-8");
79
+ }
80
+ let content = omniMdContent;
81
+ content += `
80
82
 
81
83
  ## OmniDev
82
84
 
83
85
  @import .omni/instructions.md
84
86
  `;
87
+ return content;
85
88
  }
86
89
  // ../adapters/src/codex/index.ts
87
90
  import { existsSync as existsSync2 } from "node:fs";
88
- import { writeFile as writeFile2 } from "node:fs/promises";
91
+ import { readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
89
92
  import { join as join2 } from "node:path";
90
93
  var codexAdapter = {
91
94
  id: "codex",
92
95
  displayName: "Codex",
93
- async init(ctx) {
94
- const agentsMdPath = join2(ctx.projectRoot, "AGENTS.md");
95
- const filesCreated = [];
96
- if (!existsSync2(agentsMdPath)) {
97
- await writeFile2(agentsMdPath, generateAgentsTemplate(), "utf-8");
98
- filesCreated.push("AGENTS.md");
99
- }
96
+ async init(_ctx) {
100
97
  return {
101
- filesCreated,
102
- message: filesCreated.length > 0 ? `Created ${filesCreated.join(", ")}` : "AGENTS.md already exists"
98
+ filesCreated: [],
99
+ message: "Codex adapter initialized"
103
100
  };
104
101
  },
105
- async sync(_bundle, _ctx) {
102
+ async sync(_bundle, ctx) {
103
+ const filesWritten = [];
104
+ const filesDeleted = [];
105
+ const agentsMdPath = join2(ctx.projectRoot, "AGENTS.md");
106
+ const agentsMdContent = await generateAgentsMdContent(ctx.projectRoot);
107
+ await writeFile2(agentsMdPath, agentsMdContent, "utf-8");
108
+ filesWritten.push("AGENTS.md");
106
109
  return {
107
- filesWritten: [],
108
- filesDeleted: []
110
+ filesWritten,
111
+ filesDeleted
109
112
  };
110
113
  }
111
114
  };
112
- function generateAgentsTemplate() {
113
- return `# Project Instructions
114
-
115
- <!-- Add your project-specific instructions here -->
115
+ async function generateAgentsMdContent(projectRoot) {
116
+ const omniMdPath = join2(projectRoot, "OMNI.md");
117
+ let omniMdContent = "";
118
+ if (existsSync2(omniMdPath)) {
119
+ omniMdContent = await readFile2(omniMdPath, "utf-8");
120
+ }
121
+ let content = omniMdContent;
122
+ content += `
116
123
 
117
124
  ## OmniDev
118
125
 
119
126
  @import .omni/instructions.md
120
127
  `;
128
+ return content;
121
129
  }
122
130
  // ../adapters/src/cursor/index.ts
123
131
  import { mkdirSync as mkdirSync2 } from "node:fs";
@@ -152,7 +160,7 @@ var cursorAdapter = {
152
160
  };
153
161
  // ../adapters/src/opencode/index.ts
154
162
  import { existsSync as existsSync3, mkdirSync as mkdirSync3 } from "node:fs";
155
- import { writeFile as writeFile4 } from "node:fs/promises";
163
+ import { readFile as readFile3, writeFile as writeFile4 } from "node:fs/promises";
156
164
  import { join as join4 } from "node:path";
157
165
  var opencodeAdapter = {
158
166
  id: "opencode",
@@ -160,33 +168,40 @@ var opencodeAdapter = {
160
168
  async init(ctx) {
161
169
  const opencodeDir = join4(ctx.projectRoot, ".opencode");
162
170
  mkdirSync3(opencodeDir, { recursive: true });
163
- const instructionsPath = join4(opencodeDir, "instructions.md");
164
- const filesCreated = [];
165
- if (!existsSync3(instructionsPath)) {
166
- await writeFile4(instructionsPath, generateOpencodeTemplate(), "utf-8");
167
- filesCreated.push(".opencode/instructions.md");
168
- }
169
171
  return {
170
- filesCreated,
171
- message: filesCreated.length > 0 ? `Created ${filesCreated.join(", ")}` : ".opencode/instructions.md already exists"
172
+ filesCreated: [".opencode/"],
173
+ message: "OpenCode adapter initialized"
172
174
  };
173
175
  },
174
- async sync(_bundle, _ctx) {
176
+ async sync(_bundle, ctx) {
177
+ const filesWritten = [];
178
+ const filesDeleted = [];
179
+ const opencodeDir = join4(ctx.projectRoot, ".opencode");
180
+ mkdirSync3(opencodeDir, { recursive: true });
181
+ const instructionsPath = join4(opencodeDir, "instructions.md");
182
+ const instructionsContent = await generateOpencodeInstructionsContent(ctx.projectRoot);
183
+ await writeFile4(instructionsPath, instructionsContent, "utf-8");
184
+ filesWritten.push(".opencode/instructions.md");
175
185
  return {
176
- filesWritten: [],
177
- filesDeleted: []
186
+ filesWritten,
187
+ filesDeleted
178
188
  };
179
189
  }
180
190
  };
181
- function generateOpencodeTemplate() {
182
- return `# OpenCode Instructions
183
-
184
- <!-- Add your project-specific instructions here -->
191
+ async function generateOpencodeInstructionsContent(projectRoot) {
192
+ const omniMdPath = join4(projectRoot, "OMNI.md");
193
+ let omniMdContent = "";
194
+ if (existsSync3(omniMdPath)) {
195
+ omniMdContent = await readFile3(omniMdPath, "utf-8");
196
+ }
197
+ let content = omniMdContent;
198
+ content += `
185
199
 
186
200
  ## OmniDev
187
201
 
188
202
  @import ../.omni/instructions.md
189
203
  `;
204
+ return content;
190
205
  }
191
206
  // ../adapters/src/registry.ts
192
207
  import { readEnabledProviders } from "@omnidev-ai/core";
@@ -663,7 +678,7 @@ var capabilityRoutes = buildRouteMap2({
663
678
  // src/commands/doctor.ts
664
679
  import { existsSync as existsSync5 } from "node:fs";
665
680
  import { execFile } from "node:child_process";
666
- import { readFile } from "node:fs/promises";
681
+ import { readFile as readFile4 } from "node:fs/promises";
667
682
  import { promisify } from "node:util";
668
683
  import { buildCommand as buildCommand3 } from "@stricli/core";
669
684
  var doctorCommand = buildCommand3({
@@ -803,7 +818,7 @@ async function checkRootGitignore() {
803
818
  fix: "Run: omnidev init"
804
819
  };
805
820
  }
806
- const content = await readFile(gitignorePath, "utf-8");
821
+ const content = await readFile4(gitignorePath, "utf-8");
807
822
  const lines = content.split(`
808
823
  `).map((line) => line.trim());
809
824
  const hasOmniDir = lines.includes(".omni/");
@@ -844,10 +859,12 @@ async function checkCapabilitiesDir() {
844
859
  }
845
860
 
846
861
  // src/commands/init.ts
862
+ import { exec } from "node:child_process";
847
863
  import { existsSync as existsSync6, mkdirSync as mkdirSync4 } from "node:fs";
848
- import { readFile as readFile2, writeFile as writeFile5 } from "node:fs/promises";
864
+ import { readFile as readFile5, writeFile as writeFile5 } from "node:fs/promises";
865
+ import { promisify as promisify2 } from "node:util";
849
866
  import {
850
- generateInstructionsTemplate,
867
+ generateOmniMdTemplate,
851
868
  loadConfig,
852
869
  setActiveProfile,
853
870
  syncAgentConfiguration as syncAgentConfiguration3,
@@ -857,7 +874,17 @@ import {
857
874
  import { buildCommand as buildCommand4 } from "@stricli/core";
858
875
 
859
876
  // src/prompts/provider.ts
860
- import { checkbox } from "@inquirer/prompts";
877
+ import { checkbox, confirm } from "@inquirer/prompts";
878
+ var PROVIDER_GITIGNORE_FILES = {
879
+ claude: ["CLAUDE.md", ".claude/"],
880
+ "claude-code": ["CLAUDE.md", ".claude/"],
881
+ cursor: [".cursor/"],
882
+ codex: ["AGENTS.md", ".codex/"],
883
+ opencode: [".opencode/"]
884
+ };
885
+ function getProviderGitignoreFiles(providers) {
886
+ return providers.flatMap((p) => PROVIDER_GITIGNORE_FILES[p] ?? []);
887
+ }
861
888
  async function promptForProviders() {
862
889
  const answers = await checkbox({
863
890
  message: "Select your AI provider(s):",
@@ -871,8 +898,16 @@ async function promptForProviders() {
871
898
  });
872
899
  return answers;
873
900
  }
901
+ async function promptForGitignoreProviderFiles(selectedProviders) {
902
+ const filesToIgnore = getProviderGitignoreFiles(selectedProviders);
903
+ return confirm({
904
+ message: `Add provider files to .gitignore? (${filesToIgnore.join(", ")})`,
905
+ default: false
906
+ });
907
+ }
874
908
 
875
909
  // src/commands/init.ts
910
+ var execAsync = promisify2(exec);
876
911
  async function runInit(_flags, providerArg) {
877
912
  console.log("Initializing OmniDev...");
878
913
  mkdirSync4(".omni", { recursive: true });
@@ -880,15 +915,31 @@ async function runInit(_flags, providerArg) {
880
915
  mkdirSync4(".omni/state", { recursive: true });
881
916
  await updateRootGitignore();
882
917
  let providerIds;
918
+ const isInteractive = !providerArg;
883
919
  if (providerArg) {
884
920
  providerIds = parseProviderArg(providerArg);
885
921
  } else {
886
922
  providerIds = await promptForProviders();
887
923
  }
924
+ if (isInteractive) {
925
+ const shouldIgnoreProviderFiles = await promptForGitignoreProviderFiles(providerIds);
926
+ if (shouldIgnoreProviderFiles) {
927
+ const filesToIgnore = getProviderGitignoreFiles(providerIds);
928
+ await addProviderFilesToGitignore(filesToIgnore);
929
+ const trackedFiles = await getTrackedProviderFiles(filesToIgnore);
930
+ if (trackedFiles.length > 0) {
931
+ console.log("");
932
+ console.log("⚠️ Some provider files are already tracked in git.");
933
+ console.log(" Run the following to stop tracking them:");
934
+ console.log("");
935
+ console.log(` git rm --cached ${trackedFiles.join(" ")}`);
936
+ console.log("");
937
+ }
938
+ }
939
+ }
888
940
  await writeEnabledProviders(providerIds);
889
941
  if (!existsSync6("omni.toml")) {
890
942
  await writeConfig2({
891
- project: "my-project",
892
943
  profiles: {
893
944
  default: {
894
945
  capabilities: []
@@ -903,8 +954,8 @@ async function runInit(_flags, providerArg) {
903
954
  });
904
955
  await setActiveProfile("default");
905
956
  }
906
- if (!existsSync6(".omni/instructions.md")) {
907
- await writeFile5(".omni/instructions.md", generateInstructionsTemplate(), "utf-8");
957
+ if (!existsSync6("OMNI.md")) {
958
+ await writeFile5("OMNI.md", generateOmniMdTemplate(), "utf-8");
908
959
  }
909
960
  const config = await loadConfig();
910
961
  const ctx = {
@@ -913,14 +964,9 @@ async function runInit(_flags, providerArg) {
913
964
  };
914
965
  const allAdapters = getAllAdapters();
915
966
  const selectedAdapters = allAdapters.filter((a) => providerIds.includes(a.id));
916
- const filesCreated = [];
917
- const filesExisting = [];
918
967
  for (const adapter of selectedAdapters) {
919
968
  if (adapter.init) {
920
- const result = await adapter.init(ctx);
921
- if (result.filesCreated) {
922
- filesCreated.push(...result.filesCreated);
923
- }
969
+ await adapter.init(ctx);
924
970
  }
925
971
  }
926
972
  const enabledAdapters = await getEnabledAdapters();
@@ -928,22 +974,10 @@ async function runInit(_flags, providerArg) {
928
974
  console.log("");
929
975
  console.log(`✓ OmniDev initialized for ${selectedAdapters.map((a) => a.displayName).join(" and ")}!`);
930
976
  console.log("");
931
- if (filesCreated.length > 0) {
932
- console.log("\uD83D\uDCDD Don't forget to add your project description to:");
933
- console.log(" • .omni/instructions.md");
934
- }
935
- if (filesExisting.length > 0) {
936
- console.log("\uD83D\uDCDD Add this line to your existing file(s):");
937
- for (const file of filesExisting) {
938
- console.log(` • ${file}: @import .omni/instructions.md`);
939
- }
940
- }
977
+ console.log("\uD83D\uDCDD Add your project description and instructions to OMNI.md");
978
+ console.log(" This will be transformed into provider-specific files (CLAUDE.md, AGENTS.md, etc.)");
941
979
  console.log("");
942
- console.log("\uD83D\uDCA1 Recommendation:");
943
- console.log(" Add provider-specific files to .gitignore:");
944
- console.log(" CLAUDE.md, .claude/, AGENTS.md, .cursor/, .mcp.json");
945
- console.log("");
946
- console.log(" Run 'omnidev capability list' to see available capabilities.");
980
+ console.log("\uD83D\uDCA1 Run 'omnidev capability list' to see available capabilities.");
947
981
  }
948
982
  var initCommand = buildCommand4({
949
983
  parameters: {
@@ -985,11 +1019,17 @@ function parseProviderArg(arg) {
985
1019
  return result;
986
1020
  }
987
1021
  async function updateRootGitignore() {
988
- const gitignorePath = ".gitignore";
989
1022
  const entriesToAdd = [".omni/", "omni.local.toml"];
1023
+ await addToGitignore(entriesToAdd, "OmniDev");
1024
+ }
1025
+ async function addProviderFilesToGitignore(entries) {
1026
+ await addToGitignore(entries, "OmniDev Provider Files");
1027
+ }
1028
+ async function addToGitignore(entriesToAdd, sectionHeader) {
1029
+ const gitignorePath = ".gitignore";
990
1030
  let content = "";
991
1031
  if (existsSync6(gitignorePath)) {
992
- content = await readFile2(gitignorePath, "utf-8");
1032
+ content = await readFile5(gitignorePath, "utf-8");
993
1033
  }
994
1034
  const lines = content.split(`
995
1035
  `);
@@ -1000,12 +1040,24 @@ async function updateRootGitignore() {
1000
1040
  const needsNewline = content.length > 0 && !content.endsWith(`
1001
1041
  `);
1002
1042
  const section = `${needsNewline ? `
1003
- ` : ""}# OmniDev
1043
+ ` : ""}# ${sectionHeader}
1004
1044
  ${missingEntries.join(`
1005
1045
  `)}
1006
1046
  `;
1007
1047
  await writeFile5(gitignorePath, content + section, "utf-8");
1008
1048
  }
1049
+ async function getTrackedProviderFiles(files) {
1050
+ const tracked = [];
1051
+ for (const file of files) {
1052
+ try {
1053
+ const { stdout } = await execAsync(`git ls-files "${file}"`);
1054
+ if (stdout.trim()) {
1055
+ tracked.push(file);
1056
+ }
1057
+ } catch {}
1058
+ }
1059
+ return tracked;
1060
+ }
1009
1061
 
1010
1062
  // src/commands/profile.ts
1011
1063
  import { existsSync as existsSync7 } from "node:fs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omnidev-ai/cli",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -28,7 +28,7 @@
28
28
  },
29
29
  "dependencies": {
30
30
  "@inquirer/prompts": "^8.1.0",
31
- "@omnidev-ai/core": "0.7.0",
31
+ "@omnidev-ai/core": "0.8.0",
32
32
  "@stricli/core": "^1.2.5"
33
33
  },
34
34
  "devDependencies": {