{"id":32377629,"url":"https://github.com/supermarsx/codex-cli-linker","last_synced_at":"2025-10-24T23:16:46.270Z","repository":{"id":310066145,"uuid":"1038574618","full_name":"supermarsx/codex-cli-linker","owner":"supermarsx","description":"Connect Codex-CLI to third-party LLM servers like LM Studio and Ollama","archived":false,"fork":false,"pushed_at":"2025-10-24T03:28:16.000Z","size":3685,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-24T05:34:18.282Z","etag":null,"topics":["agentic-workflow","codex","codex-cli","deepseek","gpt-oss","linker","lm-studio","lmstudio","local-llm","ollama","openai","qwen","script"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/supermarsx.png","metadata":{"files":{"readme":"readme.md","changelog":"changelog.md","contributing":null,"funding":".github/funding.yml","license":"license.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"agents.md","dco":null,"cla":null},"funding":{"github":"supermarsx"}},"created_at":"2025-08-15T13:05:46.000Z","updated_at":"2025-10-15T17:20:44.000Z","dependencies_parsed_at":null,"dependency_job_id":"76276e58-e7b5-4cbd-b59e-add54e526844","html_url":"https://github.com/supermarsx/codex-cli-linker","commit_stats":null,"previous_names":["supermarsx/codex-cli-lmstudio","supermarsx/codex-cli-linker"],"tags_count":27,"template":false,"template_full_name":null,"purl":"pkg:github/supermarsx/codex-cli-linker","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/supermarsx%2Fcodex-cli-linker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/supermarsx%2Fcodex-cli-linker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/supermarsx%2Fcodex-cli-linker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/supermarsx%2Fcodex-cli-linker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/supermarsx","download_url":"https://codeload.github.com/supermarsx/codex-cli-linker/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/supermarsx%2Fcodex-cli-linker/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":280879309,"owners_count":26406839,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-24T02:00:06.418Z","response_time":73,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agentic-workflow","codex","codex-cli","deepseek","gpt-oss","linker","lm-studio","lmstudio","local-llm","ollama","openai","qwen","script"],"created_at":"2025-10-24T23:16:43.479Z","updated_at":"2025-10-24T23:16:46.264Z","avatar_url":"https://github.com/supermarsx.png","language":"Python","funding_links":["https://github.com/sponsors/supermarsx"],"categories":[],"sub_categories":[],"readme":"\u003cimg width=\"1536\" height=\"663\" alt=\"intro-image\" src=\"https://github.com/user-attachments/assets/47eaae4a-fddc-4d6d-9db0-a05a8bca0458\" /\u003e\r\n\r\nGenerate a ready‑to‑run **Codex CLI** configuration for OpenAI‑compatible servers like **LM Studio**, **Ollama**, and others. \r\n\r\nThis small, dependency‑free Python script:\r\n\r\n- Detects a local server (LM Studio on `:1234` or Ollama on `:11434`) or uses a custom base URL.\r\n- Fetches available models from `/v1/models` and lets you pick one.\r\n- Emits a modern **`~/.codex/config.toml`** (Codex “# Config” schema) and can optionally emit **JSON** and **YAML** siblings.\r\n- Backs up any existing config (adds `.bak`).\r\n- Stores a tiny linker state (`~/.codex/linker_config.json` or `./.codex-linker.json` when using workspace override) to remember your last choices.\r\n- Can preload defaults from a remote JSON via `--config-url`.\r\n- Preview the would-be files with `--dry-run` (prints to stdout, no writes).\r\n\r\n**General Information**\r\n\r\n[![PyPI](https://img.shields.io/pypi/v/codex-cli-linker?style=flat-square\u0026label=PyPI)](https://pypi.org/project/codex-cli-linker/)\r\n[![PyPI Downloads](https://img.shields.io/pypi/dm/codex-cli-linker?logo=pypi\u0026style=flat-square\u0026label=PyPI%20downloads)](https://pypi.org/project/codex-cli-linker/)\r\n[![PyPI Total Downloads](https://img.shields.io/pepy/dt/codex-cli-linker?logo=pypi\u0026style=flat-square\u0026label=Total%20downloads)](https://pepy.tech/project/codex-cli-linker)\r\n[![Coverage](./coverage.svg)](./coverage.svg)\r\n[![Downloads](https://img.shields.io/github/downloads/supermarsx/codex-cli-linker/total?logo=github\u0026style=flat-square\u0026label=Downloads)](https://github.com/supermarsx/codex-cli-linker/releases)\r\n[![Latest Release](https://img.shields.io/github/v/release/supermarsx/codex-cli-linker?sort=semver\u0026display_name=tag\u0026logo=github\u0026style=flat-square\u0026label=Release)](https://github.com/supermarsx/codex-cli-linker/releases/latest)\r\n[![Stars](https://img.shields.io/github/stars/supermarsx/codex-cli-linker?logo=github\u0026style=flat-square\u0026label=Stars)](https://github.com/supermarsx/codex-cli-linker/stargazers)\r\n[![Forks](https://img.shields.io/github/forks/supermarsx/codex-cli-linker?logo=github\u0026style=flat-square\u0026label=Forks)](https://github.com/supermarsx/codex-cli-linker/network/members)\r\n[![Watchers](https://img.shields.io/github/watchers/supermarsx/codex-cli-linker?logo=github\u0026style=flat-square\u0026label=Watchers)](https://github.com/supermarsx/codex-cli-linker/watchers)\r\n[![Issues](https://img.shields.io/github/issues/supermarsx/codex-cli-linker?style=flat-square\u0026label=Issues)](https://github.com/supermarsx/codex-cli-linker/issues)\r\n[![Commit Activity](https://img.shields.io/github/commit-activity/m/supermarsx/codex-cli-linker?style=flat-square\u0026label=Commit%20activity)](https://github.com/supermarsx/codex-cli-linker/graphs/commit-activity)\r\n[![Made with Python](https://img.shields.io/badge/Made%20with-Python%203.8%2B-3776AB?logo=python\u0026logoColor=white\u0026style=flat-square)](https://www.python.org/)\r\n[![License](https://img.shields.io/badge/License-MIT-green?style=flat-square)](./license.md)\r\n\r\n**CI Status**\r\n\r\n[![CI](https://img.shields.io/github/actions/workflow/status/supermarsx/codex-cli-linker/ci.yml?branch=main\u0026label=CI\u0026logo=github\u0026style=flat-square)](https://github.com/supermarsx/codex-cli-linker/actions/workflows/ci.yml?query=branch%3Amain)\r\n[![Lint](https://img.shields.io/github/actions/workflow/status/supermarsx/codex-cli-linker/lint.yml?branch=main\u0026label=Lint\u0026logo=github\u0026style=flat-square)](https://github.com/supermarsx/codex-cli-linker/actions/workflows/lint.yml?query=branch%3Amain)\r\n[![Format](https://img.shields.io/github/actions/workflow/status/supermarsx/codex-cli-linker/format.yml?branch=main\u0026label=Format\u0026logo=github\u0026style=flat-square)](https://github.com/supermarsx/codex-cli-linker/actions/workflows/format.yml?query=branch%3Amain)\r\n[![Test](https://img.shields.io/github/actions/workflow/status/supermarsx/codex-cli-linker/test.yml?branch=main\u0026label=Test\u0026logo=github\u0026style=flat-square)](https://github.com/supermarsx/codex-cli-linker/actions/workflows/test.yml?query=branch%3Amain)\r\n[![Build](https://img.shields.io/github/actions/workflow/status/supermarsx/codex-cli-linker/build.yml?branch=main\u0026label=Build\u0026logo=github\u0026style=flat-square)](https://github.com/supermarsx/codex-cli-linker/actions/workflows/build.yml?query=branch%3Amain)\r\n\r\n\r\n[![Rolling Release](https://img.shields.io/github/actions/workflow/status/supermarsx/codex-cli-linker/rolling.yml?branch=main\u0026label=Rolling\u0026logo=github\u0026style=flat-square)](https://github.com/supermarsx/codex-cli-linker/actions/workflows/rolling.yml)\r\n[![Release](https://img.shields.io/github/actions/workflow/status/supermarsx/codex-cli-linker/release.yml?branch=main\u0026label=Release\u0026logo=github\u0026style=flat-square)](https://github.com/supermarsx/codex-cli-linker/actions/workflows/release.yml)\r\n[![Publish to PyPI](https://img.shields.io/github/actions/workflow/status/supermarsx/codex-cli-linker/publish.yml?branch=main\u0026label=PyPI\u0026logo=github\u0026style=flat-square)](https://github.com/supermarsx/codex-cli-linker/actions/workflows/publish.yml)\r\n[![Scoop Update](https://img.shields.io/github/actions/workflow/status/supermarsx/codex-cli-linker/scoop.yml?branch=main\u0026label=Scoop\u0026logo=github\u0026style=flat-square)](https://github.com/supermarsx/codex-cli-linker/actions/workflows/scoop.yml)\r\n[![Homebrew Update](https://img.shields.io/github/actions/workflow/status/supermarsx/codex-cli-linker/homebrew.yml?branch=main\u0026label=Homebrew\u0026logo=github\u0026style=flat-square)](https://github.com/supermarsx/codex-cli-linker/actions/workflows/homebrew.yml)\r\n\r\n\r\n## Features\r\n\r\n- Auto-detects local OpenAI-compatible servers (LM Studio, Ollama, vLLM, Text‑Gen‑WebUI OpenAI plugin, TGI shim, OpenRouter local) and normalizes base URLs.\r\n- Interactive and non-interactive flows: `--auto`, `--full-auto`, or fully manual.\r\n- Model discovery from `/v1/models` with a simple picker or direct `--model`/`--model-index`.\r\n- Produces TOML by default and optional JSON/YAML mirrors to keep schema parity.\r\n- Centralized schema shaping via a single `build_config_dict()`—no duplicated logic.\r\n- Creates safe backups (`*.bak`) before overwriting existing configs.\r\n- Remembers last choices in `~/.codex/linker_config.json` (or `./.codex-linker.json` when using workspace override) for faster repeat runs.\r\n- First-class cross‑platform UX: clean colors, concise messages, no auto‑launch side effects.\r\n- Diagnostic tooling: verbose logging, file logging, JSON logs, and remote HTTP log export.\r\n- Tunable retry/timeout parameters for flaky networks; Azure-style `api-version` support.\r\n- Security-aware: never writes API keys to disk; favors env vars (`NULLKEY` placeholder by default).\r\n  - Optional: `--keychain` can store your `--api-key` in the OS keychain (macOS Keychain, Windows DPAPI/Credential Manager, Linux Secret Service via `secretstorage`, GNU pass, or integrate with Bitwarden/1Password CLIs). The config still references the env var; secrets are never written to config files.\r\n- Compatible with Codex CLI approvals, sandbox, and history controls without post-editing.\r\n\r\n\u003e Works on macOS, Linux, and Windows. No third‑party Python packages required.\r\n\r\n\r\n## Contents\r\n- [Quick start](#quick-start)\r\n- [Installation](#installation)\r\n- [How it works](#how-it-works)\r\n- [Configuration files it writes](#configuration-files-it-writes)\r\n- [Command-line usage](#command-line-usage)\r\n- [Docker](#docker)\r\n- [Config keys written](#config-keys-written)\r\n- [Examples](#examples)\r\n- [Environment variables](#environment-variables)\r\n- [Troubleshooting](#troubleshooting)\r\n- [Windows Defender False Positive](#windows-defender-false-positive)\r\n- [Changelog](#changelog)\r\n- [Development](#development)\r\n- [License](#license)\r\n\r\n\r\n## Quick start\r\n\r\nPick one of the three options below.\r\n\r\n### A) Clone and run\r\n```bash\r\ngit clone https://github.com/supermarsx/codex-cli-linker\r\ncd codex-cli-linker\r\npython3 codex-cli-linker.py           # interactive\r\n```\r\nNon‑interactive examples:\r\n```bash\r\npython3 codex-cli-linker.py --auto        # detect server, still prompts for model\r\npython3 codex-cli-linker.py --full-auto   # detect server and first model (no prompts)\r\n```\r\n\r\n### B) Standalone executable\r\nDownload from Releases:\r\n- Windows x64: codex-cli-linker-windows-x64.exe\r\n- Windows arm64: codex-cli-linker-windows-arm64.exe\r\n- macOS x64:   codex-cli-linker-macos-x64\r\n- macOS arm64: codex-cli-linker-macos-arm64\r\n- Linux x64:   codex-cli-linker-linux-x64\r\n- Linux arm64: codex-cli-linker-linux-arm64\r\n\r\nDirect download buttons (latest assets):\r\n\r\n\u003ca href=\"https://github.com/supermarsx/codex-cli-linker/releases/latest/download/codex-cli-linker-windows-x64.exe\"\u003e\u003cimg alt=\"Download Windows x64\" src=\"https://img.shields.io/badge/⬇%20Windows-x64-0b5fff?logo=windows\u0026logoColor=white\u0026style=flat-square\" /\u003e\u003c/a\u003e\r\n\u003ca href=\"https://github.com/supermarsx/codex-cli-linker/releases/latest/download/codex-cli-linker-windows-arm64.exe\"\u003e\u003cimg alt=\"Download Windows arm64\" src=\"https://img.shields.io/badge/⬇%20Windows-arm64-0b5fff?logo=windows\u0026logoColor=white\u0026style=flat-square\" /\u003e\u003c/a\u003e\r\n\u003ca href=\"https://github.com/supermarsx/codex-cli-linker/releases/latest/download/codex-cli-linker-macos-x64\"\u003e\u003cimg alt=\"Download macOS x64\" src=\"https://img.shields.io/badge/⬇%20macOS-x64-0b5fff?logo=apple\u0026logoColor=white\u0026style=flat-square\" /\u003e\u003c/a\u003e\r\n\u003ca href=\"https://github.com/supermarsx/codex-cli-linker/releases/latest/download/codex-cli-linker-linux-x64\"\u003e\u003cimg alt=\"Download Linux x64\" src=\"https://img.shields.io/badge/⬇%20Linux-x64-0b5fff?logo=linux\u0026logoColor=white\u0026style=flat-square\" /\u003e\u003c/a\u003e\r\n\u003ca href=\"https://github.com/supermarsx/codex-cli-linker/releases/latest/download/codex-cli-linker-macos-arm64\"\u003e\u003cimg alt=\"Download macOS arm64\" src=\"https://img.shields.io/badge/⬇%20macOS-arm64-0b5fff?logo=apple\u0026logoColor=white\u0026style=flat-square\" /\u003e\u003c/a\u003e\r\n\u003ca href=\"https://github.com/supermarsx/codex-cli-linker/releases/latest/download/codex-cli-linker-linux-arm64\"\u003e\u003cimg alt=\"Download Linux arm64\" src=\"https://img.shields.io/badge/⬇%20Linux-arm64-0b5fff?logo=linux\u0026logoColor=white\u0026style=flat-square\" /\u003e\u003c/a\u003e\r\n\r\nOr fetch via curl (latest):\r\n\r\n```bash\r\n# macOS\r\ncurl -L -o codex-cli-linker-macos-x64 \\\r\n  https://github.com/supermarsx/codex-cli-linker/releases/latest/download/codex-cli-linker-macos-x64 \\\r\n  \u0026\u0026 chmod +x codex-cli-linker-macos-x64 \\\r\n  \u0026\u0026 ./codex-cli-linker-macos-x64 --auto\r\n\r\n# Linux\r\ncurl -L -o codex-cli-linker-linux-x64 \\\r\n  https://github.com/supermarsx/codex-cli-linker/releases/latest/download/codex-cli-linker-linux-x64 \\\r\n  \u0026\u0026 chmod +x codex-cli-linker-linux-x64 \\\r\n  \u0026\u0026 ./codex-cli-linker-linux-x64 --auto\r\n\r\n# Windows (PowerShell or CMD with curl available)\r\ncurl -L -o codex-cli-linker-windows-x64.exe ^\r\n  https://github.com/supermarsx/codex-cli-linker/releases/latest/download/codex-cli-linker-windows-x64.exe \u0026\u0026 \\\r\n  .\\codex-cli-linker-windows-x64.exe --auto\r\n```\r\n\r\nThen run it (example):\r\n```bash\r\n# macOS/Linux once after download\r\nchmod +x ./codex-cli-linker-*-x64\r\n./codex-cli-linker-*-x64 --auto\r\n\r\n# Windows\r\n./codex-cli-linker-windows-x64.exe --auto\r\n```\r\n\r\n### Convenience scripts (source or PyPI venv)\r\n\r\n- Run from source without installing:\r\n  - macOS/Linux: `scripts/run.sh --auto`\r\n  - Windows (PowerShell): `scripts/run.ps1 --auto`\r\n\r\n- Install from PyPI into an isolated venv under `$CODEX_HOME/venv` (or `~/.codex/venv`) and run:\r\n  - macOS/Linux: `scripts/pypi_venv_run.sh --auto`\r\n  - Windows (PowerShell): `scripts/pypi_venv_run.ps1 --auto`\r\n\r\nThese helpers avoid polluting your global Python and reuse the venv across runs.\r\n\r\n### C) PyPI (pipx or pip)\r\n```bash\r\n# Recommended: isolated install\r\npipx install codex-cli-linker\r\ncodex-cli-linker.py --auto\r\n\r\n# Or user install via pip\r\npython3 -m pip install --user codex-cli-linker\r\ncodex-cli-linker.py --auto\r\n```\r\n\r\n### D) Homebrew (macOS / Linux)\r\n```bash\r\nbrew tap supermarsx/codex-cli-linker https://github.com/supermarsx/codex-cli-linker\r\nbrew install supermarsx/codex-cli-linker/codex-cli-linker\r\ncodex-cli-linker --auto\r\n```\r\n\r\n### E) Scoop (Windows)\r\n```powershell\r\nscoop bucket add codex-cli-linker https://github.com/supermarsx/codex-cli-linker\r\nscoop install codex-cli-linker\r\ncodex-cli-linker --auto\r\n```\r\n\r\nAfter generating files, launch Codex with the printed profile:\r\n```bash\r\nnpx codex --profile lmstudio   # or: codex --profile lmstudio\r\n```\r\n\r\nMore examples:\r\n```bash\r\n# Target a specific server/model\r\npython3 codex-cli-linker.py \\\r\n  --base-url http://localhost:1234/v1 \\\r\n  --provider lmstudio \\\r\n  --profile  lmstudio \\\r\n  --model    llama-3.1-8b         # or: a substring like --model llama-3.1\r\n\r\n# Also write JSON and/or YAML alongside TOML\r\npython3 codex-cli-linker.py --json --yaml\r\n\r\n# Preview config without writing files\r\npython3 codex-cli-linker.py --dry-run --auto\r\n\r\n# Troubleshooting verbosity\r\npython3 codex-cli-linker.py --verbose --auto\r\n\r\n# Log to a file / emit JSON logs / send logs remotely\r\npython3 codex-cli-linker.py --log-file linker.log\r\npython3 codex-cli-linker.py --log-json\r\npython3 codex-cli-linker.py --log-remote http://example.com/log\r\n\r\n# Run preflight diagnostics (connectivity, permissions)\r\npython3 codex-cli-linker.py --doctor --base-url http://localhost:1234/v1\r\n\r\n# Doctor with feature probing\r\npython3 codex-cli-linker.py --doctor --doctor-detect-features --base-url http://localhost:1234/v1\r\n\r\n# Preload defaults from a remote JSON\r\npython3 codex-cli-linker.py --config-url https://example.com/defaults.json --auto\r\n```\r\n\r\n### OpenAI default linking mode\r\n\r\nCreate a profile that targets the hosted OpenAI API (no local server required). You can either select it in the interactive base URL picker or use flags:\r\n\r\n```bash\r\n# Non-interactive example\r\npython3 codex-cli-linker.py --provider openai --auto --yes \\\r\n  --model gpt-4o-mini --env-key-name OPENAI_API_KEY\r\n```\r\n\r\nTwo OpenAI auth modes are supported; both set `provider=openai`:\r\n\r\n```bash\r\n# API-key mode (preferred_auth_method=apikey)\r\npython3 codex-cli-linker.py --openai-api --auto --yes --model gpt-4o-mini\r\n\r\n# ChatGPT mode (preferred_auth_method=chatgpt)\r\npython3 codex-cli-linker.py --openai-gpt --auto --yes --model gpt-4o-mini\r\n```\r\n\r\nIn interactive mode, choose \"OpenAI API (https://api.openai.com/v1)\" when asked for the base URL.\r\nWhen provider is OpenAI, you'll be prompted to choose between API key and ChatGPT auth. If you choose API key mode, the tool offers to set/update your OPENAI_API_KEY in `~/.codex/auth.json` during the flow.\r\n\r\n### Set only OPENAI_API_KEY and quit\r\n\r\nIf you just want to set an `OPENAI_API_KEY` in `~/.codex/auth.json` and exit (no config writes):\r\n\r\n```bash\r\n# Interactive prompt (input hidden)\r\npython3 codex-cli-linker.py --set-openai-key\r\n\r\n# Non-interactive: pass the key\r\npython3 codex-cli-linker.py --set-openai-key --api-key sk-...\r\n```\r\n\r\nNotes:\r\n- Writes `~/.codex/auth.json` and creates a timestamped backup if it exists.\r\n- Never commits user configs; keep `auth.json` private (contains secrets).\r\n- No other files are modified in this mode.\r\n\r\n### Profile management\r\n\r\nYou can manage profiles before writing config:\r\n\r\n```bash\r\n# Interactive add/remove/edit of profiles during the run\r\npython3 codex-cli-linker.py --manage-profiles\r\n\r\n# Safety: prevent accidental overwrite of an existing [profiles.\u003cname\u003e]\r\n# (the tool will prompt unless --yes is used)\r\npython3 codex-cli-linker.py --profile myprofile   # will prompt if exists\r\npython3 codex-cli-linker.py --profile myprofile --overwrite-profile  # allow overwrite\r\n\r\n# Merge only the generated profiles into an existing config.toml (preserves other profiles)\r\npython3 codex-cli-linker.py --merge-profiles --profile myprofile --model llama-3.1-8b\r\n```\r\n\r\n### MCP servers\r\n\r\nConfigure external MCP servers under the top-level `mcp_servers` key (not `mcpServers`). You can manage them interactively or pass a JSON blob:\r\n\r\n```bash\r\n# Interactive management\r\npython3 codex-cli-linker.py --manage-mcp\r\n\r\n# Non-interactive via JSON (example entry named \"search\")\r\npython3 codex-cli-linker.py --auto --yes --model gpt-4o-mini --provider openai \\\r\n  --mcp-json '{\r\n    \"search\": {\r\n      \"command\": \"npx\",\r\n      \"args\": [\"-y\", \"mcp-server\"],\r\n      \"env\": {\"API_KEY\": \"value\"},\r\n      \"startup_timeout_ms\": 20000\r\n    }\r\n  }'\r\n```\r\n\r\nConfig structure produced:\r\n\r\n```toml\r\n[mcp_servers.search]\r\ncommand = \"npx\"\r\nargs = [\"-y\", \"mcp-server\"]\r\nstartup_timeout_ms = 20000 # optional; default is 10000 when omitted\r\n\r\n[mcp_servers.search.env]\r\nAPI_KEY = \"value\"\r\n```\r\n\r\n\r\n## Installation\r\n\r\nThis repository ships a single script plus a couple of optional helper scripts:\r\n\r\n```\r\n./codex-cli-linker.py          # the tool\r\n./scripts/set_env.sh           # example: set NULLKEY env (macOS/Linux)\r\n./scripts/set_env.bat          # example: set NULLKEY env (Windows)\r\n```\r\n\r\nRequirements:\r\n- **Python** 3.8+\r\n- **Codex CLI** (`codex` on PATH, or `npx codex`). If missing, the script will attempt `npm i -g @openai/codex-cli`.\r\n- A local **OpenAI‑compatible server** (LM Studio or Ollama) if you want auto‑detection.\r\n\r\n\u003e The tool itself does **not** talk to OpenAI; it only queries your local server’s `/v1/models` to list model IDs.\r\n\r\n### Install from PyPI\r\n\r\nIf you prefer a package install (no cloning needed):\r\n\r\n```bash\r\n# Recommended: isolated install via pipx\r\npipx install codex-cli-linker\r\n\r\n# Or user install via pip\r\npython3 -m pip install --user codex-cli-linker\r\n\r\n# Then run (the script is installed on your PATH)\r\ncodex-cli-linker.py --auto            # or just: codex-cli-linker.py\r\n```\r\n\r\n### Install via Homebrew\r\n\r\nHomebrew installs the tool in a virtual environment and exposes the `codex-cli-linker` entry point:\r\n\r\n```bash\r\nbrew tap supermarsx/codex-cli-linker https://github.com/supermarsx/codex-cli-linker\r\nbrew install supermarsx/codex-cli-linker/codex-cli-linker\r\ncodex-cli-linker --auto\r\n```\r\n\r\nUpgrade when a new release ships:\r\n\r\n```bash\r\nbrew update\r\nbrew upgrade codex-cli-linker\r\n```\r\n\r\nSee [docs/homebrew.md](docs/homebrew.md) for tap maintenance notes.\r\n\r\n### Install via Scoop (Windows)\r\n\r\nScoop installs the single-file executable and shims it onto your PATH:\r\n\r\n```powershell\r\nscoop bucket add codex-cli-linker https://github.com/supermarsx/codex-cli-linker\r\nscoop install codex-cli-linker\r\ncodex-cli-linker --auto\r\n```\r\n\r\nUpgrade with:\r\n\r\n```powershell\r\nscoop update codex-cli-linker\r\n```\r\n\r\nSee [docs/scoop.md](docs/scoop.md) for manifest maintenance notes.\r\n\r\nNotes:\r\n- PyPI installs the single script; there is no Python package import. Run the script by name.\r\n- On Windows PowerShell, use `py -m pip install codex-cli-linker` then run `codex-cli-linker.py`.\r\n- Homebrew keeps the package under `$(brew --cellar)/codex-cli-linker/\u003cversion\u003e` and exposes the `codex-cli-linker` entry point on your PATH.\r\n- Scoop keeps shims in `~/scoop/shims/` while the app lives under `~/scoop/apps/codex-cli-linker/current`.\r\n\r\n\r\n## How it works\r\n\r\n1. **Base URL** — Auto‑detects a running server by probing common endpoints:\r\n   - LM Studio: `http://localhost:1234/v1`\r\n   - Ollama: `http://localhost:11434/v1`\r\n   If detection fails, you can select a preset, enter a custom URL, or use your last saved URL.\r\n2. **Model pick** — Calls `GET \u003cbase\u003e/models` and lists `data[*].id` for selection.\r\n3. **Config synthesis** — Builds a single in‑memory config object that mirrors the TOML schema (root keys + `[model_providers.\u003cid\u003e]` + `[profiles.\u003cname\u003e]`).\r\n4. **Emission \u0026 backup** — Writes `~/.codex/config.toml` (always unless `--dry-run`) and, if requested, `config.json`/`config.yaml`. Any existing file is backed up to `*.bak` first.\r\n5. **State** — Saves `~/.codex/linker_config.json` so next run can preload your last base URL, provider, profile, and model.\r\n\r\n\r\n## Configuration files it writes\r\n\r\nBy default, files live under **`$CODEX_HOME`** (defaults to `~/.codex`).\r\n\r\n- `config.toml`  ← always written unless `--dry-run`\r\n- `config.json`  ← when `--json` is passed\r\n- `config.yaml`  ← when `--yaml` is passed\r\n- `linker_config.json` ← small helper file this tool uses to remember your last choices\r\n\r\n\u003e Existing `config.*` are moved to `config.*.bak` before writing.\r\n\r\n\r\n## Command-line usage\r\n\r\n```\r\npython3 codex-cli-linker.py [options]\r\n```\r\n\r\nTip: All options have short aliases (e.g., `-a` for `--auto`). Run `-h` to see the full list.\r\n\r\nAdditional handy short aliases:\r\n- `-mp/--merge-profiles`, `-mc/--merge-config`, `-mO/--merge-overwrite`\r\n- `-mm/--manage-mcp`, `-mj/--mcp-json`\r\n- `-Na/--network-access`\r\n- `-Et/--exclude-tmpdir-env-var`\r\n- `-Es/--exclude-slash-tmp`, `-ES/--no-exclude-slash-tmp`\r\n- `-Wr/--writable-roots`\r\n- `-wa/--wire-api`\r\n- `-Hh/--http-header`, `-He/--env-http-header`\r\n- `-Nt/--notify`, `-In/--instructions`, `-Tp/--trust-project`\r\n- `-Tn/--tui-notifications`, `-Tt/--tui-notification-types`\r\n- `-oa/--openai`, `-oA/--openai-api`, `-og/--openai-gpt`\r\n- `-dr/--doctor`, `-cu/--check-updates`, `-nuc/--no-update-check`\r\n- `-ll/--log-level`, `-rc/--remove-config`, `-rN/--remove-config-no-bak`, `-db/--delete-all-backups`, `-dc/--confirm-delete-backups`\r\n- `-ws/--workspace-state`, `-oc/--open-config`, `-sK/--set-openai-key`, `-kc/--keychain`, `-op/--overwrite-profile`, `-mP/--manage-profiles`\r\n\r\n**Connection \u0026 selection**\r\n- `--auto` — skip base‑URL prompt and auto‑detect a server\r\n- `--full-auto` — imply `--auto` and pick the first model with no prompts\r\n- `--model-index \u003cN\u003e` — with `--auto`/`--full-auto`, pick model by list index (default 0)\r\n- `--base-url \u003cURL\u003e` — explicit OpenAI‑compatible base URL (e.g., `http://localhost:1234/v1`)\r\n- `--model \u003cID|substring\u003e` - exact model id or a case-insensitive substring; ties break deterministically (alphabetical)\r\n- `--provider \u003cID\u003e` — provider key for `[model_providers.\u003cid\u003e]` (e.g., `lmstudio`, `ollama`, `custom`)\r\n- Presets:\r\n  - `-or, --openrouter` → provider `openrouter-remote` (`https://openrouter.ai/api/v1`)\r\n  - `-an, --anthropic` → provider `anthropic` (`https://api.anthropic.com/v1`)\r\n  - `-az, --azure` → provider `azure` (`https://\u003cresource\u003e.openai.azure.com/\u003cpath\u003e`)\r\n    - Optional: `--azure-resource \u003cNAME\u003e` and `--azure-path \u003cPATH\u003e` to synthesize `base_url`\r\n  - `-gq, --groq` → provider `groq` (`https://api.groq.com/openai/v1`)\r\n  - `-mi, --mistral` → provider `mistral` (`https://api.mistral.ai/v1`)\r\n  - `-ds, --deepseek` → provider `deepseek` (`https://api.deepseek.com/v1`)\r\n  - `-ch, --cohere` → provider `cohere` (`https://api.cohere.com/v2`)\r\n  - `-bt, --baseten` → provider `baseten` (`https://inference.baseten.co/v1`)\r\n  - `-kb, --koboldcpp` → provider `koboldcpp` (`http://localhost:5000/v1`)\r\n- `--profile \u003cNAME\u003e` — profile name for `[profiles.\u003cname\u003e]` (default deduced from provider)\r\n- `--api-key \u003cVAL\u003e` — dummy key to place in an env var\r\n- `--env-key-name \u003cNAME\u003e` — env var name that holds the API key (default `NULLKEY`)\r\n- `--config-url \u003cURL\u003e` — preload flag defaults from a remote JSON before prompting\r\n- `-V, --version` — print the tool version and exit\r\n\r\n**Behavior \u0026 UX**\r\n- `--approval-policy {untrusted,on-failure,on-request,never}` (default: `on-failure`)\r\n- `--sandbox-mode {read-only,workspace-write,danger-full-access}` (default: `workspace-write`)\r\n- `--network-access` — enable `sandbox_workspace_write.network_access` (omit to keep disabled)\r\n- `--exclude-tmpdir-env-var` — exclude `$TMPDIR` from writable roots (workspace-write only; omit to include by default)\r\n- `--exclude-slash-tmp` / `--no-exclude-slash-tmp` — exclude/include `/tmp` from writable roots (workspace-write only)\r\n- `--writable-roots \u003cCSV\u003e` — extra writable roots for workspace-write (e.g., `/workspace,/data`)\r\n- `--file-opener {vscode,vscode-insiders,windsurf,cursor,none}` (default: `vscode`)\r\n- `--open-config` — after writing files, print the exact editor command to open `config.toml` (no auto-launch)\r\n- `--tui-notifications` — enable desktop notifications in the TUI (omit to keep disabled)\r\n- `--tui-notification-types \u003cCSV\u003e` — filter to specific types: `agent-turn-complete,approval-requested`\r\n- `--reasoning-effort {minimal,low,medium,high}` (default: `low`)\r\n- `--reasoning-summary {auto,concise,detailed,none}` (default: `auto`)\r\n- `--verbosity {low,medium,high}` (default: `medium`)\r\n- `--hide-agent-reasoning` / `--show-raw-agent-reasoning`\r\n\r\n**History persistence \u0026 storage**\r\n- `--no-history` - sets `history.persistence=none` (otherwise `save-all`)\r\n- `--history-max-bytes \u003cN\u003e` - limit history size\r\n- `--disable-response-storage` - do not store responses\r\n- `--state-file \u003cPATH\u003e` - use a custom linker state JSON path (default `$CODEX_HOME/linker_config.json`)\r\n- `--workspace-state` - prefer `./.codex-linker.json` in the current directory for linker state (auto-created when missing)\r\n- `--doctor-detect-features` - while running `--doctor`, probe advanced API features (tool_choice, response_format, reasoning)\r\n\r\n**Keychain (optional)**\r\n- `--keychain {none,auto,macos,dpapi,secretstorage}` — when `--api-key` is provided, store it in an OS keychain:\r\n  - `auto` → macOS Keychain on macOS, DPAPI on Windows, Secret Service on Linux\r\n  - `macos` → macOS `security add-generic-password`\r\n  - `dpapi` → Windows Credential Manager (Generic Credential)\r\n  - `secretstorage` → Linux Secret Service (via optional `secretstorage` package)\r\n  - `none` (default) → do nothing\r\n  Notes: This is best‑effort and never required; failures are logged and ignored. Config files still use env vars — secrets are not written to TOML/JSON/YAML.\r\n\r\n**Multiple providers \u0026 profiles**\r\n- `--providers lmstudio,ollama` - add predefined routes for both providers and create matching profiles.\r\n   - Also supports: `vllm`, `tgwui`, `tgi`, `openrouter` (common local ports are probed automatically).\r\n\r\n**Dry-run diffs**\r\n- `--dry-run --diff` - show colorized, symbol-rich diffs in TTY (falls back to unified diff when color is unavailable). Additions are green `+`, deletions red `-`, unchanged lines dim.\r\n\r\n**Non-interactive**\r\n- `--yes` - suppress prompts when inputs are fully specified (implies `--auto` and defaults `--model-index 0` when `--model` is not provided).\r\n- Honors `NO_COLOR` and non‑TTY: disables ANSI; banners are omitted to keep logs clean.\r\n\r\n### CLI Quick Reference\r\n\r\n- Guided pipeline: `codex-cli-linker.py --guided` (add `--no-emojis` to hide emojis)\r\n- OpenAI (API key): `codex-cli-linker.py --openai-api --auto --yes --model gpt-4o-mini`\r\n- OpenAI (ChatGPT): `codex-cli-linker.py --openai-gpt --auto --yes --model gpt-4o-mini`\r\n- Azure: `codex-cli-linker.py --azure --azure-resource \u003cname\u003e --azure-api-version 2025-04-01-preview --auto`\r\n- LM Studio: `codex-cli-linker.py --openrouter --auto` (example preset; see Provider presets)\r\n- Continuous logs (no auto‑clear): add `--continuous` to any interactive run\r\n- ESC in menus: backs to the previous menu level\r\n- Experimental: `-U` `--experimental-resume`, `-I` `--experimental-instructions-file`, `-X` `--experimental-use-exec-command-tool`, `-O` `--responses-originator-header-internal-override`, `-M` `--preferred-auth-method`, `-W` `--tools-web-search`, `-z` `--azure-api-version`, `-K` `--request-max-retries`, `-S` `--stream-max-retries`, `-e` `--stream-idle-timeout-ms`\r\n\r\nNote: All single-letter shorts are already used; `--log-level` offers an alias `--level` for convenience. Use `--level info` (for example) or `-v` for a quick DEBUG/WARNING toggle.\r\n\r\nPost‑run report includes: target file path, backup path (if created), profile, provider, model, context window, and max tokens.\r\n\r\n## Docker\r\n\r\nBuild the image locally (includes Codex CLI and this tool):\r\n```bash\r\ndocker build -t codex-cli-linker:local .\r\n```\r\n\r\nRun with your `~/.codex` mounted so configs persist on the host:\r\n```bash\r\ndocker run --rm -it \\\r\n  -e CODEX_HOME=/data/.codex \\\r\n  -v \"$HOME/.codex:/data/.codex\" \\\r\n  codex-cli-linker:local --auto\r\n```\r\n\r\nCompose option (uses `docker-compose.yml`):\r\n```bash\r\ndocker compose up --build codex-linker\r\n```\r\n\r\nNotes:\r\n- To target a local server on the host, use `--base-url http://host.docker.internal:1234/v1` on macOS/Windows. On Linux, consider `network_mode: host` in compose.\r\n- The container never auto-launches external apps; it only prints suggested commands.\r\n- `--history-max-bytes \u003cN\u003e` — sets `history.max_bytes`\r\n- `--disable-response-storage` — sets `disable_response_storage=true`\r\n\r\n**Networking \u0026 compatibility**\r\n- `--azure-api-version \u003cVER\u003e` — adds `query_params.api-version=\u003cVER\u003e` to the selected provider\r\n- `--request-max-retries \u003cN\u003e` (default: `4`)\r\n- `--stream-max-retries \u003cN\u003e` (default: `10`)\r\n- `--stream-idle-timeout-ms \u003cMS\u003e` (default: `300000`)\r\n- `--chatgpt-base-url \u003cURL\u003e` — optional alternate base for ChatGPT‑authored requests\r\n- `--preferred-auth-method {chatgpt,apikey}` (default: `apikey`)\r\n- `--tools-web-search` — sets `tools.web_search=true`\r\n- `--wire-api {chat,responses}` — wire protocol for the provider\r\n- `--http-header KEY=VAL` — static HTTP header (repeatable)\r\n- `--env-http-header KEY=ENV_VAR` — env‑sourced header (repeatable)\r\n- Authorization headers use Bearer tokens for these presets:\r\n  - OpenRouter (remote), Groq, Mistral, DeepSeek, Cohere, Baseten → `Authorization: Bearer \u003cenv value\u003e`\r\n  - Anthropic → `x-api-key: \u003cenv value\u003e`\r\n  - Azure OpenAI → `api-key: \u003cenv value\u003e`\r\n- `--notify '[\"program\",\"arg1\",...]'` or `program,arg1,...` — top‑level `notify`\r\n- `--instructions \u003cTEXT\u003e` — top‑level `instructions`\r\n- `--trust-project \u003cPATH\u003e` — mark a project/worktree as trusted (repeatable)\r\n\r\n**Output formats**\r\n- `--json` — also write `~/.codex/config.json`\r\n- `--yaml` — also write `~/.codex/config.yaml`\r\n- `--dry-run` — print configs to stdout without writing files\r\n\r\n**Diagnostics**\r\n- `--verbose` — enable INFO/DEBUG logging\r\n- `--log-file \u003cPATH\u003e` — append logs to a file\r\n- `--log-json` — also emit logs as JSON to stdout\r\n- `--log-remote \u003cURL\u003e` — POST log records to an HTTP endpoint\r\n\r\n\u003e The `--launch` flag is intentionally disabled; the script prints the exact `npx codex --profile \u003cname\u003e` command (or `codex --profile \u003cname\u003e` if installed) instead of auto‑launching.\r\n\r\n\r\n## Config keys written\r\n\r\nAt a glance, the script writes:\r\n\r\n- **Root keys**\r\n  - `model` — chosen model id\r\n  - `model_provider` — provider key (e.g., `lmstudio`, `ollama`)\r\n  - `approval_policy`, `sandbox_mode`, `file_opener`\r\n  - `model_reasoning_effort`, `model_reasoning_summary`, `model_verbosity`\r\n  - `model_context_window` *(best‑effort auto‑detected; 0 if unknown)*\r\n  - `model_max_output_tokens`\r\n  - `project_doc_max_bytes`\r\n  - `hide_agent_reasoning`, `show_raw_agent_reasoning`, `model_supports_reasoning_summaries`\r\n  - `preferred_auth_method`\r\n  - `tools.web_search`\r\n  - `tui.style` — TUI style (e.g., `table`)\r\n  - `tui.notifications` — boolean to enable all notifications, or array of types\r\n  - `disable_response_storage`\r\n  - `history.persistence` \u0026 `history.max_bytes`\r\n\r\n- **`[model_providers.\u003cid\u003e]`** *(only the active one is emitted)*\r\n  - `name` — human label (e.g., \"LM Studio\", \"Ollama\")\r\n  - `base_url` — your selected base URL, normalized\r\n  - `env_key` — environment variable holding the API key\r\n  - `wire_api` — `chat` or `responses`\r\n  - `request_max_retries`, `stream_max_retries`, `stream_idle_timeout_ms`\r\n  - `http_headers` — static headers map\r\n  - `env_http_headers` — env‑sourced headers map\r\n  - `query_params.api-version` *(when `--azure-api-version` is provided)*\r\n\r\n- **`mcp_servers.\u003cid\u003e`**\r\n  - `command`, `args`, `env`, optional `startup_timeout_ms` (default: 10000)\r\n\r\n- **`sandbox_workspace_write`** (applies when `sandbox_mode = \"workspace-write\"`)\r\n  - `writable_roots` — extra writable roots (cwd, $TMPDIR, and /tmp are writable by default unless excluded)\r\n  - `network_access` — allow network in workspace-write (default: false)\r\n  - `exclude_tmpdir_env_var` — exclude `$TMPDIR` (default: false)\r\n  - `exclude_slash_tmp` — exclude `/tmp` (default: false)\r\n\r\n- **`[profiles.\u003cname\u003e]`**\r\n  - `model`, `model_provider`\r\n  - `model_context_window`, `model_max_output_tokens`\r\n  - `approval_policy`\r\n\r\n\u003e The tool deliberately **does not store API keys in the file**.\r\n\r\n\r\n## Examples\r\n\r\n### Minimal LM Studio profile\r\n\r\n```toml\r\n# ~/.codex/config.toml (excerpt)\r\nmodel = \"llama-3.1-8b\"\r\nmodel_provider = \"lmstudio\"\r\napproval_policy = \"on-failure\"\r\nsandbox_mode = \"workspace-write\"\r\nfile_opener = \"vscode\"\r\nmodel_reasoning_effort = \"low\"\r\nmodel_reasoning_summary = \"auto\"\r\nmodel_verbosity = \"medium\"\r\nmodel_context_window = 0\r\nmodel_max_output_tokens = 0\r\nproject_doc_max_bytes = 1048576\r\n\r\n[tools]\r\nweb_search = false\r\n\r\n[history]\r\npersistence = \"save-all\"\r\nmax_bytes = 0\r\n\r\n[model_providers.lmstudio]\r\nname = \"LM Studio\"\r\nbase_url = \"http://localhost:1234/v1\"\r\nwire_api = \"chat\"\r\nrequest_max_retries = 4\r\nstream_max_retries = 10\r\nstream_idle_timeout_ms = 300000\r\n\r\n[profiles.lmstudio]\r\nmodel = \"llama-3.1-8b\"\r\nmodel_provider = \"lmstudio\"\r\nmodel_context_window = 0\r\nmodel_max_output_tokens = 0\r\napproval_policy = \"on-failure\"\r\n```\r\n\r\n### Ollama profile\r\n\r\n```toml\r\n[model_providers.ollama]\r\nname = \"Ollama\"\r\nbase_url = \"http://localhost:11434/v1\"\r\nwire_api = \"chat\"\r\nrequest_max_retries = 4\r\nstream_max_retries = 10\r\nstream_idle_timeout_ms = 300000\r\n\r\n[profiles.ollama]\r\nmodel = \"llama3\"\r\nmodel_provider = \"ollama\"\r\nmodel_context_window = 0\r\nmodel_max_output_tokens = 0\r\napproval_policy = \"on-failure\"\r\n```\r\n\r\n### Also write JSON/YAML\r\n\r\n```bash\r\npython3 codex-cli-linker.py --json --yaml\r\nls ~/.codex/\r\n# config.toml  config.toml.bak  config.json  config.yaml  linker_config.json\r\n```\r\n\r\n\r\n## Environment variables\r\n\r\n- `CODEX_HOME` — overrides the config directory (default: `~/.codex`).\r\n- `NULLKEY` — default env var this tool initializes to `\"nullkey\"` so configs never need to include secrets; change with `--env-key-name`.\r\n  - Optional helper scripts:\r\n    - macOS/Linux: `source scripts/set_env.sh`\r\n    - Windows: `scripts\\set_env.bat`\r\n\r\n\u003e If your provider requires a key, prefer exporting it in your shell and letting Codex read it from the environment rather than writing it to disk.\r\n\r\n\r\n## Troubleshooting\r\n\r\n- **“No server auto‑detected.”**  \r\n  Ensure LM Studio’s local server is running (check *Developer → Local Server* is enabled) or that Ollama is running. Otherwise pass `--base-url`.\r\n\r\n- **“Models list is empty.”**  \r\n  Your server didn’t return anything from `GET /v1/models`. Verify the endpoint and that at least one model is downloaded/available.\r\n\r\n- **Network errors**  \r\n  Use `--request-max-retries`, `--stream-max-retries`, or `--stream-idle-timeout-ms` to tune resilience for flaky setups.\r\n\r\n- **History \u0026 storage**  \r\n  If you’re in a restricted environment, add `--disable-response-storage` and/or `--no-history` when generating the config.\r\n\r\n- **Azure/OpenAI compatibility**\r\n  When talking to Azure‑hosted compatible endpoints, pass `--azure-api-version \u003cYYYY-MM-DD\u003e` to set `query_params.api-version`.\r\n\r\n\r\n\r\n\r\n## Windows Defender False Positive\r\n\r\nThe single‑file binaries are built with PyInstaller, which can occasionally trigger false‑positive warnings from Windows Defender or other AV engines.\r\n\r\nMitigations\r\n- Prefer the source or PyPI install: `pipx install codex-cli-linker` (or `pip install --user codex-cli-linker`) and run `codex-cli-linker`.\r\n- Build locally from source: `python -m pip install build pyinstaller \u0026\u0026 pyinstaller -F -n codex-cli-linker codex-cli-linker.py`.\r\n- Verify checksum against the GitHub Release artifact SHA shown in the release details.\r\n- Optionally upload the artifact to VirusTotal to confirm multi‑engine status.\r\n\r\nNote: We do not include third‑party code in the binary; it is produced directly from this repository’s source. If warnings persist, prefer the PyPI or source‑based install method.\r\n\r\n\r\n## Changelog\r\n\r\nSee [changelog.md](./changelog.md) for a summary of notable changes by version.\r\n\r\n\r\n## Development\r\n\r\nSee [development.md](./development.md) for CI, release, and code map information.\r\n\r\n### CMake pipeline (optional)\r\n\r\nYou can use CMake to run common tasks for this Python tool (no extra Python deps required):\r\n\r\n```bash\r\n# Configure once\r\ncmake -S . -B build\r\n\r\n# Syntax check\r\ncmake --build build --target check\r\n\r\n# Run unit tests via CTest\r\ncmake --build build --target test        # or: ctest --test-dir build -V\r\n\r\n# Run the tool with flags controlled by cache vars\r\ncmake -S . -B build \\\r\n  -DCODEX_AUTO=ON \\\r\n  -DCODEX_JSON=ON \\\r\n  -DCODEX_BASE_URL=http://localhost:1234/v1\r\ncmake --build build --target run\r\n\r\n# Handy aggregate target\r\ncmake --build build --target ci          # runs check + test\r\n```\r\n\r\nConfigurable cache variables for `run`:\r\n- `CODEX_AUTO`, `CODEX_FULL_AUTO`, `CODEX_JSON`, `CODEX_YAML`, `CODEX_DRY_RUN`, `CODEX_VERBOSE`\r\n- `CODEX_BASE_URL`, `CODEX_PROVIDER`, `CODEX_PROFILE`, `CODEX_MODEL`, `CODEX_MODEL_INDEX`\r\n\r\nThis keeps side effects explicit (no auto-launch) and matches the repo’s cross‑platform, no‑deps philosophy.\r\n\r\n### Makefile helpers (optional)\r\n\r\nGNU Make wrapper around the CMake targets:\r\n\r\n```bash\r\n# Configure \u0026 run checks/tests\r\nmake configure\r\nmake check\r\nmake test\r\n\r\n# Run the tool (pass flags as variables)\r\nmake run AUTO=1 JSON=1 BASE_URL=http://localhost:1234/v1\r\n\r\n# Aggregate\r\nmake ci\r\n\r\n# Clean build dir\r\nmake clean\r\n```\r\n\r\n\r\n\r\n## License\r\n\r\nReleased under the MIT License. See [license.md](./license.md) for details.\r\n\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsupermarsx%2Fcodex-cli-linker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsupermarsx%2Fcodex-cli-linker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsupermarsx%2Fcodex-cli-linker/lists"}