-
Notifications
You must be signed in to change notification settings - Fork 1
Multi Project Mode
By default the server is pinned to one project: --work-dir is the project root, and every tool resolves against it. Multi-project mode turns --work-dir into an access root — a directory beneath which each conversation selects its own project — so one running server can serve many repositories without a process per repo.
Enable it with --multi-project or "multiProject": true.
codexify --work-dir /path/to/projects --multi-projectOne static codexify.config.json is still read once at startup; selection changes only the effective work directory the project tools use, never the server configuration itself.
Each conversation binds a project exactly once, through set_project_root. When the exact path isn't known, list_projects provides a search step first.
-
Path rules. The path is relative to the access root or absolute, but its canonical target must be an existing directory inside that root. Traversal (
..) and symlink escapes are rejected after canonicalization, so a link pointing outside can't smuggle a selection past the check. -
Git repository URLs.
pathmay instead be a provider-agnostic HTTPS or SSH clone URL ending in.git, including GitLab and SCP-style SSH forms such asgit@gitlab.com:group/repository.git. GitHub additionally accepts repository-root URLs without.gitplus HTTPS branch (/tree/<branch>), pull-request (/pull/<number>), and full-40-hex commit (/commit/<sha>) URLs. Codexify reuses exactly one matching local checkout when possible, otherwise it clones intoprojectCloneDir/--project-clone-dir(default: the access root). Provider-agnostic URLs select the repository's default checkout. Targeted GitHub URLs fetch the exact branch/PR/commit; when an existing source checkout is on another commit, Codexify leaves it untouched and binds a detached managed worktree at the requested target. Credential-bearing HTTPS URLs, query strings/fragments,file://, plain HTTP,git://, and other arbitrary transports are rejected. -
Binding scope. The binding belongs to the ChatGPT conversation, keyed from
_meta["openai/session"](hashed, never stored raw). Simultaneous chats can hold different projects, and a later turn recovers its own root after MCP reconnects or a server restart. A client with no ChatGPT conversation metadata falls back to a binding that lasts only the current MCP transport session. - No switching. A conversation cannot switch roots once bound — start another chat for another project. Re-selecting the same canonical path is idempotent.
-
Before selection. Project-scoped tools are unavailable and say why.
list_projectsandset_project_rootare the two project-independent tools present for this workflow.
list_projects searches a read-only catalogue assembled from two sources:
-
Native Codex trust table — Codex records trust decisions in its user config:
[projects."/absolute/path/to/project"] trust_level = "trusted"
Codexify reads those paths as candidates. It doesn't treat the table as exhaustive — entries may be stale or lack descriptions.
-
Explicit
projectCatalog.entries— operator-authored providers that can add aliases/descriptions or supply projects absent from the native table:{ "multiProject": true, "projectCatalog": { "codexConfig": { "enabled": true, "trustedOnly": true }, "entries": [ { "path": "codexify", "name": "Codexify", "aliases": ["ChatGPT MCP bridge"], "description": "Rust MCP bridge exposing local programming tools to ChatGPT" } ] } }
Every candidate still passes Codexify's own checks: it must exist, resolve to a directory, and canonicalize to the access root itself or a descendant. Missing entries, files, and symlink escapes are skipped; duplicate canonical targets are merged. Native Codex trust is only catalogue metadata plus the default trustedOnly filter — it never grants access outside --work-dir, and neither does an explicit entry.
list_projects returns a selector relative to the access root, passable unchanged as set_project_root.path. Its optional query matches names, aliases, descriptions, and selectors case-insensitively with exact/prefix/substring ranking. It never binds automatically — if several results are plausible, the agent's instructions require it to ask you rather than guess, because a wrong binding can't be changed in that conversation.
The native table is read live on every list_projects call, so newly trusted projects become discoverable without restarting. Project-local .codex/config.toml layers are not scanned — they matter only after selection. Catalogue construction never opens a candidate's README, source, .codex/, or AGENTS.md; contents stay unread until the conversation selects that project.
Git URL selection is separate from catalogue listing. Before cloning, Codexify checks the conventional destination, catalogue candidates, and immediate children of projectCloneDir, comparing normalized remotes at each Git top level. Exactly one match is reused; multiple matches are rejected as ambiguous. Non-GitHub URLs must end in .git unless a matching checkout already exists. GitHub branch names may contain /; everything after /tree/ is treated as the branch ref.
- Worktrees. With the default worktree mode, the first conversation selecting a Git project uses the source checkout directly; a second conversation gets a detached managed worktree so concurrent chats never edit the same tree. See Worktree Isolation.
-
Saved state. With an explicit
memory.dir, each selected project gets its own hashed child directory. Conversation bindings stay enabled even whenmemory.enabledisfalse. See Context and Memory. - Diff checkpoints. Namespaced per conversation/project pair. See Diff Checkpoints.
To clear a stray binding, delete its file under ~/.codexify/conversation-projects/. There is no tool to re-point an already-bound conversation. A managed worktree stays referenced while its binding exists; startup cleanup skips referenced or dirty worktrees and only removes older clean, unreferenced entries beyond keepCount.
codexify projects list --work-dir /path/to/projects
codexify projects list --work-dir /path/to/projects --query "codexify"
codexify projects list --work-dir /path/to/projects --json
codexify projects list --work-dir /path/to/projects --show-skipped--show-skipped (local-only) also prints paths rejected as missing, untrusted, or outside the access root, plus merged duplicates. See CLI Reference.
Multi-project selection isolates Codexify's structured tools and per-conversation state — it is not an OS sandbox. The entire access-root subtree is intentionally selectable by a new conversation, so treat the whole subtree as sensitive. See Security Model.
-
Worktree Isolation · Connecting to ChatGPT (multi-project onboarding) · Configuration (
projectCatalog,multiProject).
Repository · Releases · Report an issue · MIT License
Getting started
Reference
How it works
Multi-project
Extending
Operations