Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "loop-it",
"version": "0.3.19",
"version": "0.3.20",
"description": "Find, recommend, and run bounded agent loops across turn-based, goal-based, time-based, and proactive patterns.",
"author": {
"name": "Loop it",
Expand Down
2 changes: 1 addition & 1 deletion .codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "loop-it",
"version": "0.3.19",
"version": "0.3.20",
"description": "Find, recommend, and run bounded agent loops across turn-based, goal-based, time-based, and proactive patterns.",
"author": {
"name": "Loop it",
Expand Down
2 changes: 1 addition & 1 deletion .cursor-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "loop-it",
"version": "0.3.19",
"version": "0.3.20",
"description": "Find, recommend, and run bounded agent loops across turn-based, goal-based, time-based, and proactive patterns.",
"homepage": "https://swarmixai.com/experiments/loop-it-poc",
"license": "MIT",
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

## Unreleased

## 0.3.20

### Fixed

- `loop-it run --execute codex` and `loop-it doctor` now discover the Codex executable bundled with Codex Desktop on macOS when `codex` is not available on the terminal `PATH`. Explicit `--codex-bin` and `LOOP_IT_CODEX_BIN` overrides still take precedence.

## 0.3.19

### Changed
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ Loop it has three product verbs:
2. **Recommend** one bundled loop with a verifier gate.
3. **Run** the selected loop in Codex, Claude Code, or Cursor until proof, blocker, or approval.

`loop-it run --execute codex` is the happy path when the user wants work done. It inspects repo signals, picks or applies a loop, writes the run contract, calls Codex CLI, reruns the verifier after each pass, and repeats up to the iteration cap until proof, a repeated failure, a blocker, or approval-sensitive work stops it. `loop-it run` without `--execute` prepares the same loop contract and launch prompt without calling Codex. `write` and `start` are lower-level preparation commands. A result that only creates or edits `.loop-it` files is not a successful repair.
`loop-it run --execute codex` is the happy path when the user wants work done. It inspects repo signals, picks or applies a loop, writes the run contract, calls Codex CLI, reruns the verifier after each pass, and repeats up to the iteration cap until proof, a repeated failure, a blocker, or approval-sensitive work stops it. When `codex` is not on the terminal `PATH`, Loop It automatically discovers the executable bundled with Codex Desktop on macOS. Use `--codex-bin <path>` or `LOOP_IT_CODEX_BIN` only when you need an explicit override. `loop-it run` without `--execute` prepares the same loop contract and launch prompt without calling Codex. `write` and `start` are lower-level preparation commands. A result that only creates or edits `.loop-it` files is not a successful repair.

Add `--checker codex` when the run needs a second, read-only review after the verifier passes. The checker inspects the changed files, verifier output, Codex output, and `.loop-it/progress.json`, then writes a checker receipt. Loop it records whether the checker passed, blocked, was inconclusive, or was skipped.

Expand All @@ -96,7 +96,7 @@ Use `loop-it schedules list` to see local schedules and whether the Codex heartb

Use `loop-it github pr` when the trigger should come from GitHub. It reads a PR through the GitHub CLI, chooses `review-comment-resolver-routine`, `ci-health-watch`, or `pr-review-watch`, writes a read-only connector snapshot under `.loop-it/connectors/github/`, and creates a local schedule. It never comments, pushes, requests review, merges, deploys, or changes GitHub state without explicit approval.

Use `loop-it doctor` when the user needs to know whether Loop It is actually ready. It reports the local package version, npm latest version, personal Codex plugin cache version, project skill install, Codex CLI availability, schedule records, Codex heartbeat files, and GitHub CLI auth when connector state exists. It exits non-zero for real blockers such as missing Codex CLI, missing configured heartbeat files, or missing GitHub auth for GitHub-backed schedules.
Use `loop-it doctor` when the user needs to know whether Loop It is actually ready. It reports the local package version, npm latest version, personal Codex plugin cache version, project skill install, Codex CLI availability (including the Codex Desktop fallback), schedule records, Codex heartbeat files, and GitHub CLI auth when connector state exists. It exits non-zero for real blockers such as missing Codex CLI, missing configured heartbeat files, or missing GitHub auth for GitHub-backed schedules.

Before `--execute codex` starts, Loop it runs a readiness preflight:

Expand Down
1 change: 1 addition & 0 deletions bin/loop-it.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ Install options:
Run execution options:
--execute codex Call Codex CLI and rerun the verifier after each pass
--checker codex Run a second read-only checker after the verifier passes
--codex-bin <path> Override PATH and Codex Desktop executable discovery
--worktree Create a fresh git worktree/branch and run Codex there`);
}

Expand Down
2 changes: 1 addition & 1 deletion docs/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ npx @fhajjej/loop-it@latest run \
--worktree
```

`run --execute codex` inspects repo signals, recommends the highest-confidence loop, writes the loop contract, calls `codex exec`, reruns the verifier after each pass, and repeats up to the iteration cap until proof, a repeated failure, a blocker, or approval-sensitive work stops it. Add `--checker codex` when you want a second read-only Codex pass to inspect the changed files, verifier output, Codex output, and `.loop-it/progress.json` before the run is accepted. Add `--worktree` when Codex should edit a fresh git worktree/branch instead of your current checkout. When the verifier passes, the CLI prints a `Run proof` summary and records a machine-readable `proof` object with the selected loop, executor, verifier, checker result, final Codex output path, changed files, optional worktree metadata, and per-iteration evidence.
`run --execute codex` inspects repo signals, recommends the highest-confidence loop, writes the loop contract, calls `codex exec`, reruns the verifier after each pass, and repeats up to the iteration cap until proof, a repeated failure, a blocker, or approval-sensitive work stops it. If `codex` is not on the terminal `PATH`, Loop It discovers the executable bundled with Codex Desktop on macOS; `--codex-bin <path>` and `LOOP_IT_CODEX_BIN` are explicit overrides. Add `--checker codex` when you want a second read-only Codex pass to inspect the changed files, verifier output, Codex output, and `.loop-it/progress.json` before the run is accepted. Add `--worktree` when Codex should edit a fresh git worktree/branch instead of your current checkout. When the verifier passes, the CLI prints a `Run proof` summary and records a machine-readable `proof` object with the selected loop, executor, verifier, checker result, final Codex output path, changed files, optional worktree metadata, and per-iteration evidence.

Omit `--execute codex` when you only want to prepare the launch prompt for a human to paste into Codex, Claude Code, or Cursor.

Expand Down
2 changes: 1 addition & 1 deletion docs/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ For Codex CLI execution, use `run --execute codex` instead of only preparing a l
npx @fhajjej/loop-it@latest run --goal "Fix failing CI" --check "npm run check" --agent codex --execute codex --checker codex --worktree
```

That path calls Codex, reruns the verifier after each pass, repeats up to the iteration cap, optionally runs a read-only checker, prints a `Run proof` summary on success, and records the selected loop, executor, verifier, checker result, Codex output paths, changed files, optional worktree metadata, and per-iteration evidence in `.loop-it/progress.json`.
That path calls Codex, reruns the verifier after each pass, repeats up to the iteration cap, optionally runs a read-only checker, prints a `Run proof` summary on success, and records the selected loop, executor, verifier, checker result, Codex output paths, changed files, optional worktree metadata, and per-iteration evidence in `.loop-it/progress.json`. On macOS, Loop It automatically uses the Codex executable bundled with Codex Desktop when `codex` is not on your terminal `PATH`. Use `--codex-bin <path>` or `LOOP_IT_CODEX_BIN` to override discovery.

Use `--worktree` when you want Codex to edit a fresh branch/worktree instead of the current checkout. Loop it chooses `origin/main`, `main`, `origin/master`, `master`, or `HEAD` as the base unless you pass `--worktree-base <ref>`.

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@fhajjej/loop-it",
"version": "0.3.19",
"version": "0.3.20",
"description": "Portable loop router, library, launcher, and Agent Skill for finding, recommending, and running bounded agent loops across turn-based, goal-based, time-based, and proactive patterns.",
"type": "module",
"author": {
Expand Down Expand Up @@ -41,7 +41,7 @@
"test": "node tests/smoke-install.mjs",
"sync:project": "node ./bin/loop-it.mjs install --agent all --scope project --force",
"sync:codex-plugin": "node scripts/sync-codex-plugin.mjs",
"check": "node --check bin/loop-it.mjs && node --check skills/loop-it/scripts/create-loop.mjs && node --check skills/loop-it/scripts/select-loop.mjs && node --check skills/loop-it/scripts/start-loop.mjs && node --check skills/loop-it/scripts/run-loop.mjs && node --check skills/loop-it/scripts/schedule-loop.mjs && node --check skills/loop-it/scripts/github-connector.mjs && node --check skills/loop-it/scripts/doctor.mjs && node --check scripts/sync-codex-plugin.mjs && node --check tests/smoke-install.mjs && node --check tests/public-install-smoke.mjs && node --check tests/run-proof-smoke.mjs && node --check tests/readiness-preflight-smoke.mjs && node -e \"const fs=require('fs'); ['.codex-plugin/plugin.json','.claude-plugin/plugin.json','.cursor-plugin/plugin.json','skills/loop-it/references/library/loops.json','skills/loop-it/references/library/schema.json','skills/loop-it/references/library/evals.json'].forEach((file)=>JSON.parse(fs.readFileSync(file,'utf8')))\" && node skills/loop-it/scripts/select-loop.mjs eval && npm run smoke && npm run smoke:run-proof && npm run smoke:readiness && npm pack --dry-run",
"check": "node --check bin/loop-it.mjs && node --check skills/loop-it/scripts/create-loop.mjs && node --check skills/loop-it/scripts/select-loop.mjs && node --check skills/loop-it/scripts/start-loop.mjs && node --check skills/loop-it/scripts/run-loop.mjs && node --check skills/loop-it/scripts/lib/codex-cli.mjs && node --check skills/loop-it/scripts/schedule-loop.mjs && node --check skills/loop-it/scripts/github-connector.mjs && node --check skills/loop-it/scripts/doctor.mjs && node --check scripts/sync-codex-plugin.mjs && node --check tests/smoke-install.mjs && node --check tests/public-install-smoke.mjs && node --check tests/run-proof-smoke.mjs && node --check tests/readiness-preflight-smoke.mjs && node -e \"const fs=require('fs'); ['.codex-plugin/plugin.json','.claude-plugin/plugin.json','.cursor-plugin/plugin.json','skills/loop-it/references/library/loops.json','skills/loop-it/references/library/schema.json','skills/loop-it/references/library/evals.json'].forEach((file)=>JSON.parse(fs.readFileSync(file,'utf8')))\" && node skills/loop-it/scripts/select-loop.mjs eval && npm run smoke && npm run smoke:run-proof && npm run smoke:readiness && npm pack --dry-run",
"smoke": "node tests/smoke-install.mjs",
"smoke:public-install": "node tests/public-install-smoke.mjs",
"smoke:public-codex": "node tests/public-install-smoke.mjs --codex-run",
Expand Down
9 changes: 7 additions & 2 deletions skills/loop-it/scripts/doctor.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { spawnSync } from "node:child_process";
import { homedir } from "node:os";
import { resolveCodexCli } from "./lib/codex-cli.mjs";

const scriptDir = dirname(fileURLToPath(import.meta.url));
const packageRoot = resolve(scriptDir, "..", "..", "..");
Expand Down Expand Up @@ -40,7 +41,11 @@ function buildDoctorReport(options) {
const schedules = loadSchedules(cwd);
const githubConnectorCount = countJsonFiles(resolve(cwd, ".loop-it", "connectors", "github"));
const githubRequired = githubConnectorCount > 0 || schedules.some((schedule) => schedule.connector === "github");
const codexCli = checkCommand(stringArg(options["codex-bin"], "codex"), ["--version"]);
const codexResolution = resolveCodexCli({ requested: stringArg(options["codex-bin"], "") });
const codexCli = {
...checkCommand(codexResolution.bin, ["--version"]),
source: codexResolution.source,
};
const githubCli = githubRequired || options["check-gh"]
? checkCommand(stringArg(options["gh-bin"], "gh"), ["auth", "status"])
: { status: "not-required", ok: true, output: "", detail: "No GitHub connector state found." };
Expand Down Expand Up @@ -545,7 +550,7 @@ function printUsage() {
Options:
--cwd <path> Repository to inspect. Default: current directory.
--codex-home <path> Codex home for plugin and automation files. Default: $CODEX_HOME or ~/.codex.
--codex-bin <path> Codex executable override. Default: codex.
--codex-bin <path> Override PATH and Codex Desktop executable discovery.
--gh-bin <path> GitHub CLI executable override. Default: gh.
--npm-bin <path> npm executable override. Default: npm.
--check-gh Check gh auth even when no GitHub connector state exists.
Expand Down
82 changes: 82 additions & 0 deletions skills/loop-it/scripts/lib/codex-cli.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { accessSync, constants } from "node:fs";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Reject directories as executable candidates.

accessSync(path, constants.X_OK) can succeed for a traversable directory on POSIX. A directory named codex in PATH or a desktop candidate can therefore be selected, causing downstream spawnSync execution to fail instead of trying another candidate.

Proposed fix
-import { accessSync, constants } from "node:fs";
+import { accessSync, constants, statSync } from "node:fs";

 function isExecutable(path) {
   try {
+    if (!statSync(path).isFile()) {
+      return false;
+    }
     accessSync(path, constants.X_OK);
     return true;
   } catch {
     return false;
   }
 }

Also applies to: 71-77

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@skills/loop-it/scripts/lib/codex-cli.mjs` at line 1, Update
executable-candidate validation in the codex CLI resolution flow to require both
execute access and a non-directory filesystem entry. Apply this check
consistently to PATH candidates and desktop candidates before selecting them, so
directory entries are skipped and resolution continues to the next candidate.

import { homedir } from "node:os";
import { delimiter, resolve } from "node:path";

const CODEX_DESKTOP_RELATIVE_PATHS = [
["Applications", "ChatGPT.app", "Contents", "Resources", "codex"],
["Applications", "Codex.app", "Contents", "Resources", "codex"],
];

export function resolveCodexCli(options = {}) {
const env = options.env ?? process.env;
const requested = nonEmpty(options.requested) || nonEmpty(env.LOOP_IT_CODEX_BIN) || "codex";

if (requested !== "codex") {
return {
bin: requested,
source: options.requested ? "argument" : "environment",
};
Comment on lines +12 to +18

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Base the source on the normalized override.

A truthy whitespace-only options.requested causes the environment binary to be selected while the result is incorrectly labeled "argument". This makes doctor’s reported source inconsistent with the actual resolver decision.

Proposed fix
-  const requested = nonEmpty(options.requested) || nonEmpty(env.LOOP_IT_CODEX_BIN) || "codex";
+  const requestedArgument = nonEmpty(options.requested);
+  const requestedEnvironment = nonEmpty(env.LOOP_IT_CODEX_BIN);
+  const requested = requestedArgument || requestedEnvironment || "codex";

...
-      source: options.requested ? "argument" : "environment",
+      source: requestedArgument ? "argument" : "environment",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const requested = nonEmpty(options.requested) || nonEmpty(env.LOOP_IT_CODEX_BIN) || "codex";
if (requested !== "codex") {
return {
bin: requested,
source: options.requested ? "argument" : "environment",
};
const requestedArgument = nonEmpty(options.requested);
const requestedEnvironment = nonEmpty(env.LOOP_IT_CODEX_BIN);
const requested = requestedArgument || requestedEnvironment || "codex";
if (requested !== "codex") {
return {
bin: requested,
source: requestedArgument ? "argument" : "environment",
};
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@skills/loop-it/scripts/lib/codex-cli.mjs` around lines 12 - 18, Update the
source selection in the resolver around requested so it reflects the normalized
override used to choose the binary, not the raw options.requested truthiness.
Label the result as "argument" only when the normalized argument value is
selected; otherwise preserve "environment" for the environment-derived binary.

}

if (isCommandOnPath("codex", env)) {
return {
bin: "codex",
source: "path",
};
}

for (const candidate of desktopCandidates(env)) {
if (isExecutable(candidate)) {
return {
bin: candidate,
source: "desktop",
};
}
}

return {
bin: "codex",
source: "missing",
};
}

function desktopCandidates(env) {
const home = nonEmpty(env.HOME) || homedir();
const candidates = CODEX_DESKTOP_RELATIVE_PATHS.map((parts) => resolve(home, ...parts));

if (process.platform === "darwin") {
candidates.push(
"/Applications/ChatGPT.app/Contents/Resources/codex",
"/Applications/Codex.app/Contents/Resources/codex"
);
}

return [...new Set(candidates)];
}
Comment on lines +43 to +55

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Only consider desktop candidates on macOS.

The home-relative candidates are built before the Darwin check, so Linux and Windows also treat ~/Applications/ChatGPT.app/.../codex and ~/Applications/Codex.app/.../codex as desktop binaries. If such a path exists, downstream execution will label it "desktop" and invoke it.

Proposed fix
 function desktopCandidates(env) {
+  if (process.platform !== "darwin") {
+    return [];
+  }
+
   const home = nonEmpty(env.HOME) || homedir();
   const candidates = CODEX_DESKTOP_RELATIVE_PATHS.map((parts) => resolve(home, ...parts));

-  if (process.platform === "darwin") {
-    candidates.push(
-      "/Applications/ChatGPT.app/Contents/Resources/codex",
-      "/Applications/Codex.app/Contents/Resources/codex"
-    );
-  }
+  candidates.push(
+    "/Applications/ChatGPT.app/Contents/Resources/codex",
+    "/Applications/Codex.app/Contents/Resources/codex"
+  );

   return [...new Set(candidates)];
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function desktopCandidates(env) {
const home = nonEmpty(env.HOME) || homedir();
const candidates = CODEX_DESKTOP_RELATIVE_PATHS.map((parts) => resolve(home, ...parts));
if (process.platform === "darwin") {
candidates.push(
"/Applications/ChatGPT.app/Contents/Resources/codex",
"/Applications/Codex.app/Contents/Resources/codex"
);
}
return [...new Set(candidates)];
}
function desktopCandidates(env) {
if (process.platform !== "darwin") {
return [];
}
const home = nonEmpty(env.HOME) || homedir();
const candidates = CODEX_DESKTOP_RELATIVE_PATHS.map((parts) => resolve(home, ...parts));
candidates.push(
"/Applications/ChatGPT.app/Contents/Resources/codex",
"/Applications/Codex.app/Contents/Resources/codex"
);
return [...new Set(candidates)];
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@skills/loop-it/scripts/lib/codex-cli.mjs` around lines 43 - 55, Update
desktopCandidates so CODEX_DESKTOP_RELATIVE_PATHS are resolved and included only
when process.platform is "darwin"; keep the absolute macOS application paths and
deduplication behavior unchanged, and ensure non-macOS platforms return no
desktop candidates.


function isCommandOnPath(command, env) {
const pathEntries = String(env.PATH ?? "")
.split(delimiter)
.map((entry) => entry.trim().replace(/^"|"$/g, ""))
.filter(Boolean);
const extensions = process.platform === "win32"
? String(env.PATHEXT ?? ".EXE;.CMD;.BAT;.COM").split(delimiter)
: [""];

return pathEntries.some((entry) =>
extensions.some((extension) => isExecutable(resolve(entry, `${command}${extension}`)))
);
}

function isExecutable(path) {
try {
accessSync(path, constants.X_OK);
return true;
} catch {
return false;
}
}

function nonEmpty(value) {
return typeof value === "string" && value.trim() ? value.trim() : "";
}
14 changes: 11 additions & 3 deletions skills/loop-it/scripts/run-loop.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { basename, dirname, relative, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { spawnSync } from "node:child_process";
import { findLoopById, recommendLoop } from "./select-loop.mjs";
import { resolveCodexCli } from "./lib/codex-cli.mjs";

const scriptDir = dirname(fileURLToPath(import.meta.url));
const startScript = resolve(scriptDir, "start-loop.mjs");
Expand Down Expand Up @@ -161,9 +162,12 @@ process.exit(0);
function executeWithCodex(run) {
const launchPath = resolve(run.cwd, ".loop-it", "LAUNCH.md");
const outputPath = resolve(run.cwd, stringArg(args["codex-output"], ".loop-it/CODEX_FINAL.md"));
const codexBin = stringArg(args["codex-bin"], "codex");
const codexCli = resolveCodexCli({ requested: stringArg(args["codex-bin"], "") });
const codexBin = codexCli.bin;
const sandbox = stringArg(args["codex-sandbox"], "workspace-write");
const checkerBin = stringArg(args["checker-bin"], codexBin);
const checkerBin = args["checker-bin"]
? resolveCodexCli({ requested: stringArg(args["checker-bin"], "") }).bin
: codexBin;
const checkerSandbox = stringArg(args["checker-sandbox"], "read-only");
const checkerOutputPath = resolve(run.cwd, stringArg(args["checker-output"], ".loop-it/CODEX_CHECKER.md"));

Expand All @@ -177,6 +181,10 @@ function executeWithCodex(run) {
let previousVerifierOutput = "";
const proofIterations = [];

if (codexCli.source === "desktop") {
console.log(`Using Codex Desktop CLI: ${codexBin}`);
}

for (let iteration = 1; iteration <= run.maxIterations; iteration += 1) {
const iterationOutputPath = outputPathForIteration(outputPath, iteration);
mkdirSync(dirname(iterationOutputPath), { recursive: true });
Expand Down Expand Up @@ -1218,7 +1226,7 @@ Options:
--max-iterations <n> Iteration cap, default selected loop cap
--execute <none|codex> Execute the generated loop with Codex CLI, default none
--checker <none|codex> Optional read-only checker after the verifier passes, default none
--codex-bin <path> Codex executable for --execute codex, default codex
--codex-bin <path> Codex executable override; otherwise discover PATH or Codex Desktop
--codex-sandbox <mode> Codex sandbox mode, default workspace-write; use none to omit
--codex-output <path> Last Codex message path, default .loop-it/CODEX_FINAL.md
--checker-bin <path> Checker Codex executable, default --codex-bin
Expand Down
Loading