@fractary/codex-cli 0.10.19 → 0.10.22

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/cli.js CHANGED
@@ -223,7 +223,7 @@ init_esm_shims();
223
223
  // src/commands/config/initialize.ts
224
224
  init_esm_shims();
225
225
  function configInitializeCommand() {
226
- const cmd = new Command("config-initialize");
226
+ const cmd = new Command("config-init");
227
227
  cmd.description("Initialize codex section in .fractary/config.yaml (requires base config from @fractary/core)").option("--org <slug>", 'Organization slug (e.g., "fractary")').option("--project <name>", "Project name (default: derived from directory)").option("--codex-repo <name>", 'Codex repository name (e.g., "codex.fractary.com")').option("--sync-preset <name>", "Sync preset (standard, minimal)", "standard").option("--force", "Overwrite existing codex section").option("--no-mcp", "Skip MCP server installation").option("--json", "Output as JSON").action(async (options) => {
228
228
  try {
229
229
  const configManager = createConfigManager(process.cwd());
@@ -924,6 +924,23 @@ function getEnvironmentBranch(config, env) {
924
924
  };
925
925
  return envMap[env] || env;
926
926
  }
927
+ async function commitAndPushToCodex(codexRepoPath, projectName, syncedCount) {
928
+ try {
929
+ const { RepoManager } = await import('@fractary/core/repo');
930
+ const repoManager = new RepoManager({ platform: "github" }, codexRepoPath);
931
+ repoManager.stageAll();
932
+ if (repoManager.isClean()) {
933
+ return { pushed: false, message: "No changes to push - codex is already up to date" };
934
+ }
935
+ repoManager.commit({
936
+ message: `Sync ${syncedCount} files from ${projectName}`
937
+ });
938
+ repoManager.push({});
939
+ return { pushed: true, message: "Changes pushed to codex repository" };
940
+ } catch (error) {
941
+ return { pushed: false, message: error.message };
942
+ }
943
+ }
927
944
  function syncCommand() {
928
945
  const cmd = new Command("sync");
929
946
  cmd.description("Sync single project with codex repository").argument("[name]", "Project name (auto-detected if not provided)").option("--env <env>", "Target environment (dev/test/staging/prod)", "prod").option("--dry-run", "Show what would sync without executing").option("--direction <dir>", "Sync direction (to-codex/from-codex/bidirectional)", "bidirectional").option("--include <pattern>", "Include files matching pattern (can be used multiple times)", (val, prev) => prev.concat([val]), []).option("--exclude <pattern>", "Exclude files matching pattern (can be used multiple times)", (val, prev) => prev.concat([val]), []).option("--force", "Force sync without checking timestamps").option("--json", "Output as JSON").option("--work-id <id>", "GitHub issue number or URL to scope sync to").action(async (name, options) => {
@@ -1094,12 +1111,33 @@ function syncCommand() {
1094
1111
  console.error(chalk10.dim(` ${error.message}`));
1095
1112
  process.exit(1);
1096
1113
  }
1114
+ const codexProjectDir = path4.join(codexRepoPath, "projects", projectName);
1115
+ let existingCodexFiles = [];
1116
+ try {
1117
+ const codexGlobMatches = await globSync("**/*", {
1118
+ cwd: codexProjectDir,
1119
+ dot: true,
1120
+ nodir: true
1121
+ });
1122
+ const fsPromises = await import('fs/promises');
1123
+ existingCodexFiles = await Promise.all(
1124
+ codexGlobMatches.map(async (filePath) => {
1125
+ const fullPath = path4.join(codexProjectDir, filePath);
1126
+ const stats = await fsPromises.stat(fullPath);
1127
+ return {
1128
+ path: filePath,
1129
+ size: stats.size,
1130
+ mtime: stats.mtimeMs
1131
+ };
1132
+ })
1133
+ );
1134
+ } catch {
1135
+ }
1097
1136
  plan = await syncManager.createPlan(
1098
1137
  config.organization,
1099
1138
  projectName,
1100
1139
  sourceDir,
1101
- [],
1102
- // Empty target - treat all files as creates
1140
+ existingCodexFiles,
1103
1141
  syncOptions
1104
1142
  );
1105
1143
  plan.source = sourceDir;
@@ -1151,6 +1189,10 @@ function syncCommand() {
1151
1189
  return;
1152
1190
  }
1153
1191
  const result2 = await syncManager.executePlan(plan, syncOptions);
1192
+ let pushResult;
1193
+ if (direction === "to-codex" && codexRepoPath && result2.synced > 0) {
1194
+ pushResult = await commitAndPushToCodex(codexRepoPath, projectName, result2.synced);
1195
+ }
1154
1196
  let status;
1155
1197
  if (!result2.success && result2.synced === 0) {
1156
1198
  status = "failure";
@@ -1169,7 +1211,8 @@ function syncCommand() {
1169
1211
  skipped: result2.skipped,
1170
1212
  duration: result2.duration,
1171
1213
  errors: result2.errors
1172
- }
1214
+ },
1215
+ ...pushResult ? { pushed: pushResult.pushed, pushMessage: pushResult.message } : {}
1173
1216
  }, null, 2));
1174
1217
  return;
1175
1218
  }
@@ -1238,28 +1281,12 @@ Total: ${plan.totalFiles} files (${formatBytes(plan.totalBytes)})`));
1238
1281
  const result = await syncManager.executePlan(plan, syncOptions);
1239
1282
  const duration = Date.now() - startTime;
1240
1283
  if (direction === "to-codex" && codexRepoPath && result.synced > 0) {
1241
- try {
1242
- if (!options.json) {
1243
- console.log(chalk10.blue("Committing and pushing to codex..."));
1244
- }
1245
- const { RepoManager } = await import('@fractary/core/repo');
1246
- const repoManager = new RepoManager({ platform: "github" }, codexRepoPath);
1247
- repoManager.stageAll();
1248
- if (repoManager.isClean()) {
1249
- if (!options.json) {
1250
- console.log(chalk10.dim(" No changes to push - codex is already up to date"));
1251
- }
1252
- } else {
1253
- repoManager.commit({
1254
- message: `Sync ${result.synced} files from ${projectName}`
1255
- });
1256
- repoManager.push({});
1257
- if (!options.json) {
1258
- console.log(chalk10.dim(" Changes pushed to codex repository"));
1259
- }
1260
- }
1261
- } catch (error) {
1262
- console.error(chalk10.red("Error pushing to codex:"), error.message);
1284
+ console.log(chalk10.blue("Committing and pushing to codex..."));
1285
+ const pushResult = await commitAndPushToCodex(codexRepoPath, projectName, result.synced);
1286
+ if (pushResult.pushed) {
1287
+ console.log(chalk10.dim(` ${pushResult.message}`));
1288
+ } else {
1289
+ console.log(chalk10.dim(` ${pushResult.message}`));
1263
1290
  }
1264
1291
  }
1265
1292
  console.log("");