CORTEX Docs

Get started

User guide

Cortex is a Windows desktop app that runs AI coding-agent CLIs (Claude Code, Codex, OpenCode) as managed "agents" and lets you control them from one window. This guide describes what the app does today (version 0.2.0). Anything not built yet is labelled "not implemented".

Design record: docs/adr/0001 to 0011 (Portuguese). Roadmap: Plan.md and TODO.md.

1. Requirements and starting the app#

  • Windows only. The code compiles on other systems with stubs, but starting agents needs ConPTY and Job Objects, which exist only in the Windows build. Nothing runs agents elsewhere.
  • Install Cortex with Cortex_0.2.0_x64-setup.exe and start it from the Start Menu (installation), or run it from source with Start.bat in the repository root. It builds the UI (npm install the first time, then npm run build in apps/desktop/ui), builds cortex-desktop with cargo, and starts target\debug\cortex-desktop.exe. Start.bat release builds and runs the release binary, which has no console window. Needs Node.js with npm, Rust 1.89 or newer and the Tauri 2 Windows prerequisites.
  • You need at least one agent CLI, signed in. From the window you can create only Claude Code agents. The Runtimes screen (section 7) shows which CLIs Cortex finds and installs the missing ones you select; you can also install them yourself (see 8.2 for where Cortex looks).
  • One Cortex instance per data directory. A second launch fails with instance.already_running.

2. First launch#

  1. A splash screen shows the logo and a progress bar. While the Core starts it says "Core is starting" (the Core phase in lower case). It stays at least 450 ms.
  2. If the Core cannot start (bad config.json, another instance, unwritable data directory) the splash shows "Cortex Core could not start" with the error message, a remediation line, the error code, a correlation ID and a collapsible list of causes. The window stays open so you can read it. See section 12.
  3. When the Core is ready the workspace appears, on the Agents screen with the Orchestrator panel open on the right. On the first launch Cortex creates %LOCALAPPDATA%\Cortex and writes a default config.json there.
  4. On the first start of an installation with no agents, the window opens on the Runtimes screen in setup mode ("Set up agent CLIs"), described in section 7. Skip for now, or Continue after an install, leads to the Agents screen, and the setup is not offered on its own again.
  5. A new install shows "No agents yet." and a New agent button. The sidebar footer shows WORKSPACE with the Core phase (ready), the version (v0.2.0) and the data directory, with your home folder abbreviated to ~ (hover for the full path).

Closing the window shuts the Core down: running agents are stopped and their process trees are ended.

3. Window layout and title bar#

The window is frameless on Windows (minimum size 800x500). The UI draws its own title bar:

  • Drag regions: the sidebar brand row, the screen header and the right-panel header, all 40 px high. Double-click one to maximize or restore.
  • Minimize, maximize/restore and close buttons are at the right end of the rightmost header: the right panel's header when the panel is open, otherwise the screen header. The splash has its own set.
  • Resize from any edge or corner (native invisible borders).

Zones: the sidebar (screens), the main screen, and the right panel with two tabs, Orchestrator and Console. The header button "Hide orchestrator" / "Show console" (named after the active tab) toggles the panel. Drafts typed in either tab survive tab switches.

4. Agents#

4.1 Add an agent#

Click New agent (header, or the empty state). The button is disabled until the agents and projects have loaded. The dialog "Add agent" has:

Field Behavior
Name Required. 1 to 64 characters, no control characters.
Project Shown only if a project exists; lists name — folder and "New project…". Defaults to the first project.
Project name, Folder path Shown for a new project. The folder must be an absolute path to an existing directory (typed; there is no folder picker). It is where the agent works.
Runtime Select one of the runtimes the Core lists (Claude Code, Codex, OpenCode). A runtime marked "(unavailable)" can be chosen, but its agent will not start until the runtime is installed. Terminal is offered only for a runtime that has an interactive terminal.
Set orchestrator role A checkbox, off by default. It makes the agent an orchestrator instead of a worker (see 4.7). It is available only for a runtime that can host one (Claude Code) and, once set, the interaction is Structured and cannot be changed.
Interaction Terminal (default where the runtime has one) or Structured. See 4.3.
Model Choose from the models the runtime offers. Default leaves the choice to the runtime. Claude Code offers sonnet, opus and haiku; OpenCode offers the provider/model names that opencode models lists; Codex offers only Default, because its CLI cannot list its models.

Create agent makes the agent in state CREATED and selects it. Nothing runs until you start it. If creating the agent fails after a new project was created, a retry reuses that project. Escape or Cancel closes the dialog.

Codex and OpenCode agents are created from the same dialog, or through the MCP create_agent tool (section 7); they then appear in the grid like any other. A project cannot be renamed or removed from the window, and an agent cannot be renamed. An agent is removed from the Stats side of its card with Remove, then Confirm remove; the button is available only when the agent is created, stopped, failed or crashed, so stop a running agent first. Removal deletes the agent for good.

4.2 Agent states and actions#

State Meaning
CREATED Defined, never started.
STARTING Runtime launching. A start waits up to 60 s for the runtime to report ready.
READY Running and idle.
BUSY Running a task from the Orchestrator (section 6).
PAUSED Held by you (see 4.6): its process and session are kept, but Cortex hands it nothing until you resume it.
STOPPING / STOPPED Shutting down / not running.
FAILED Start failed or was refused. The last failure (message and code) is shown on the card and in the Console.
CRASHED The runtime process ended unexpectedly, or Cortex ended abruptly while the agent was active.

Buttons are enabled only by state:

Action Allowed in
Start CREATED, STOPPED, FAILED, CRASHED
Pause READY, structured mode, with no reply running
Resume PAUSED
Stop STARTING, READY, BUSY, PAUSED
Restart READY, BUSY, PAUSED, STOPPED, FAILED, CRASHED (a new session with the same identity and config)
Send instruction READY, structured mode only
Edit CREATED, STOPPED, FAILED, CRASHED
Remove CREATED, STOPPED, FAILED, CRASHED

While a command of an agent is in flight, Start and Restart are disabled; Stop stays available, so a start that hangs can be cancelled. Stopping or restarting a BUSY agent cancels the task attempt it runs; the task goes back to waiting for an agent.

After a Cortex restart, agent definitions and projects are kept. A normal close stops the agents, so they come back STOPPED. If Cortex ended abruptly (crash, process killed, or a shutdown that did not finish), agents that were STARTING, READY, BUSY, PAUSED or STOPPING come back CRASHED with code recovery.cortex_restart. Start them again either way. Sessions are not resumed.

4.3 Interaction modes#

  • Structured: Cortex runs claude -p with stream-json over pipes. You read the output in the Console tab and the card's mini terminal, and send instructions from the Console. Anything the CLI would ask approval for is denied (--permission-prompts none); there is no permission system yet.
  • Terminal: Cortex starts the real interface of the CLI (claude, codex or opencode) in a pseudoconsole and draws it in the agent's card (xterm.js). You type in the card. Permission prompts, sign-in and trust dialogs are the CLI's own and you answer them there; for OpenCode, Cortex makes edits, commands and web fetches ask you, which its own default would not. Codex and OpenCode 2 run with their own server inside the agent's process (--no-daemon, --standalone), so stopping the agent ends everything it started and it does not share a background server with your other windows. The Console shows a note, "This agent runs in terminal mode", and what you send from it is typed into the terminal. An Orchestrator task is typed into the agent's terminal and counts as finished when the terminal has been quiet for 15 seconds (ADR 0032); it has no result text, and a task that needs a model, handoff or isolated workspace skips terminal agents. You can answer the CLI's prompts in the card while the task runs.

The terminal attaches while the agent is READY. When the session ends the last screen stays with a dim "Session ended." note; the next start resets it. The card shows "Starting…", "Opening the terminal…", "No terminal session." or "Start the agent to open its terminal." as appropriate.

4.4 Edit agent#

Card back, Edit button (the tooltip says "Stop the agent to edit it." when disabled). The dialog shows the name (read-only) and Interaction. Only the interaction mode can be changed from the window. Terminal is disabled for a runtime without an interactive terminal (all three shipped runtimes have one). The Core refuses the change while the agent has a live session and shows its error in the dialog. Model, name, project and runtime cannot be changed. The dialog also has the orchestrator checkbox (4.7): the role of an agent can be set or cleared here while the agent has no live session.

4.5 Agent cards#

Cards are in a grid. Click a card (or focus it and press Enter/Space) to select it; the Console tab follows the selection. The search field filters by name, ID or runtime.

Front: state dot, name, last 8 characters of the agent ID, Stats button, a line STATE · runtime · project · interaction, the last failure if any, and the output area. For structured agents the output area is a read-only mini terminal with the last 9 lines (stderr lines carry a stderr tag); live cards refresh about once per second. For terminal agents it is the live terminal.

Back (Stats button; the button on the back is labelled Terminal and flips back): state, pid, runtime, interaction, project, workdir, model, created, updated, last failure; plus Start, Stop, Restart and Edit. Command errors show here as well. The first button is Pause, or Resume while the agent is paused. A card of an orchestrator carries an Orchestrator tag next to its name.

4.6 Context menu and Pause#

Right-click a card, on its front or its back, to open Cortex's own menu for that agent (the browser's menu is not used for an agent). With the keyboard, focus the card and press the context-menu key or Shift+F10. The right click also selects the card.

The menu has six rows, always in this order: Pause (Resume while the agent is paused), Stop, Start, Edit, Restart and Remove. Each is enabled only when the Core would accept it, and a disabled row says why in its tooltip; Remove asks for a confirmation first. While a command of the agent is in flight everything but Stop is disabled. Choosing a row closes the menu; so do Escape, a click or a right click elsewhere, scrolling the wheel, resizing the window or switching to another window. The menu opens at the pointer and flips to stay inside the window. The arrow keys, Home and End move between the enabled rows, Enter or Space chooses one and Tab closes the menu.

What each row does is what the same button does on the card back, with its result shown at the bottom of the window: a note while a Stop, Start or Restart is running, then Stopped alpha, Started alpha, or the Core's reason and what to do about it when it refuses. Remove is the only row that goes through a dialog: "Remove agent?" has Cancel (focused first) and Remove agent, and removal is final; the card back keeps its own two-step Remove button.

Pause holds an idle agent: a READY, structured agent with no reply running becomes PAUSED, and Cortex keeps its process and session but sends it nothing (no instruction from the console, no task, and it is never released for being idle) until Resume brings it back to READY. A pause never interrupts work: an agent that is replying or running a task, or a terminal agent (whose CLI takes your keys directly), cannot be paused, and its row says so. A paused agent can be stopped or restarted; it cannot be started, edited or removed until then. If its process ends while it is paused it becomes CRASHED like any other.

4.7 Orchestrator role#

An orchestrator coordinates other agents instead of doing their work. Tick Set orchestrator role when you add the agent, or in its Edit dialog while it is stopped. It is available for a runtime that can keep an orchestrator to coordinating (Claude Code today), and an orchestrator is always structured. The role is stored with the agent and survives a restart of Cortex.

An orchestrator has no tool to read, change or run anything in your project, and the Core enforces that, not only its instructions. Every tool request it makes is answered by the Core: only the Cortex tools are allowed and everything else (shell, file and web tools) is refused at once, whatever you or Automatic Decisions would say, and listed in Approvals as decided by the role. Claude Code is also started with no built-in tools at all and with the Cortex server as its only MCP server. What an orchestrator can do with the Cortex tools is create and configure worker agents in its own project, start them, and read, send and acknowledge messages; it cannot stop, interrupt or message an agent directly, create objectives or tasks, make another orchestrator, or change a role. Tasks are never given to it.

You talk to it in its Console, like any structured agent. It reaches workers through the message bus: a worker reads its inbox in its next turn, so a worker that is idle sees the message when it next receives a turn. If a worker fails or cannot start, the orchestrator can see it (get_agent_status shows the state and the last failure, and a refused start_agent returns the Core's reason), and its instructions tell it to report that to you and never to do the work itself. An orchestrator does not start if the MCP server is off or its runtime cannot host one.

5. Console tab (selected agent)#

  • Header: agent name and state, runtime and project, and Start/Stop/Restart.
  • Output: stdout and stderr lines of the current agent, read every 500 ms while the agent starts, stops, runs a task or replies, and the window is visible. Cortex keeps up to 256 KiB per agent in memory (lines over 8 KiB are cut and marked); older lines are dropped and the output says "N earlier lines were dropped". The last 2,000 lines of each agent are also kept, redacted, in transcripts\<agent>.jsonl in the data directory: after Cortex restarts the console shows them, then a line "— Cortex restarted: the lines above are from before —". Removing the agent deletes its transcript.
  • Replying: while a structured agent answers an instruction it stays READY, and the console header shows "Replying…" (the card's task line says "READY · replying"). Send waits until the reply ends; what you type stays in the field.
  • Input: "context: name (id)", a text field and Send. Enter sends, Shift+Enter inserts a newline. An instruction must have 1 to 100,000 characters. The field is disabled unless the agent is READY and structured; the tooltip says why (not started, running a task, replying, terminal mode).
  • A terminal-mode Claude Code agent in a folder it has never trusted first asks whether to trust it. The card says "Waiting for you in the terminal: trust this folder?" and the console takes no instruction until you answer in the card's terminal (Enter or Esc).
  • Failures: a command error is shown with Dismiss; for a FAILED or CRASHED agent the persisted last failure is shown too.

With no agent selected the tab says "Select an agent."

6. Orchestrator panel and Tasks screen#

The Orchestrator hands work to agents that already exist. Nothing is planned by an LLM, and it does not create agents.

  • Typing an instruction in the Orchestrator tab and sending it creates one Objective containing one Task. The title is the first non-blank line, cut to 200 characters; the full text is the task description (at most 20,000 characters).
  • The task goes to the project of the selected agent; if no agent is selected and there is exactly one project, that project. The context line shows project <name>. The field is disabled otherwise ("Select an agent to choose the project of the task", or "No project yet. Add an agent first"). The task is not tied to the selected agent: any eligible agent of the project may take it.
  • Eligible agents are structured, READY and not busy, with a runtime that reports the end of a turn (all three do). One task is one turn. The Orchestrator runs at most orchestrator.max_parallel_tasks tasks at once (default 2), each on its own agent; orchestrator.max_parallel_tasks_per_project and orchestrator.max_parallel_tasks_per_runtime can lower that for one project or one runtime, and a task then goes to an agent of another runtime when one can run it. The agent shows BUSY while it runs one; manual instructions to it are refused.
  • A retryable failed attempt is retried once by default, after a 5 s backoff (doubling per retry, capped at 60 s).
  • The panel lists objectives oldest first. Each shows its status, the agent a running task is on, why a waiting task waits, the final message of a completed task ("Finished without a final message." if none; "(truncated)" if cut) or the cause of a failure or cancellation. The panel header shows ready, N running, loading or unavailable.

Statuses. Task: CREATED, READY, RUNNING, BLOCKED, COMPLETED, FAILED, CANCELLED. Objective: RUNNING, PAUSED, BLOCKED, COMPLETED, FAILED, CANCELLED, derived from its tasks and from whether a person paused it.

Pause and resume: on a RUNNING objective (Orchestrator tab), Pause stops anything new from starting while the attempts that run end by themselves, and Interrupt also interrupts the running turns (their attempts end CANCELLED and no retry is spent). A paused objective shows what the pause did and why, its waiting tasks say "The objective is paused", and Resume lets them run again, an interrupted one as its next attempt. MCP clients see the same state and can use the same actions (pause_objective, resume_objective, cancel_objective, reassign_task).

Move: in the Tasks screen, Move on a task that waits (CREATED, READY or BLOCKED, with no attempt running) opens a list with the agents of its project and "Any eligible agent". The move is recorded on the task with who decided it. It is refused while the previous agent still ends its last attempt. Objectives with several tasks show a graph line under each task ("Step 2 · after Setup · unblocks Ship"); tasks of one step can run side by side. A task with evidence has a disclosure under it: why it is complete, what its attempts handed over, the worktree they ran in and the decisions and moves recorded.

Cancel: the Cancel button on a RUNNING objective (Orchestrator tab) cancels what has not ended. In the Tasks screen, Cancel appears on each CREATED, READY or RUNNING task; it also cancels the tasks that depend on it. A running attempt ends CANCELLED and the agent is released; if its turn cannot be interrupted the agent is stopped.

Tasks screen: a table with Objective, Task, Status, Attempts (count · last outcome · agent), Detail (waiting reason, result excerpt or cause) and Cancel. Refresh re-reads it; it also updates on Core events. Objectives with several tasks and dependencies can be created only through MCP create_objective; they show up here.

There is no supervisor or timeout: if a CLI hangs without ending its turn, the task stays RUNNING until you cancel it.

7. Processes, Runtimes, MCP and Skills screens#

Processes#

Lists the runtime processes the Core has alive: PID, PPID, command, owner (agent name and short ID), kind (always runtime), started (local time) and Memory (the working set of the runtime's main process, not of its children; a dash when Windows does not say). A Codex agent starts a process for each turn only, so a ready Codex agent has no row between turns. Search filters by PID, command or owner. Refresh re-reads the list; it also follows Core events. The CLI process of a terminal-mode agent appears here like any other.

Runtimes#

One row per agent CLI (Claude Code, Codex, OpenCode) with what Cortex found: status, version and executable. Cortex finds a CLI the way an agent start would, then asks it for its version and whether it is signed in, with read-only commands; their answers are never stored or logged. Check again repeats the checks.

Status Meaning
Ready Found, answers, and signed in.
Sign-in required Found, but not signed in. The row shows the command to run in a terminal (claude auth login, codex login).
Free models only OpenCode with no provider signed in; opencode auth login adds one.
Installed — sign-in not verified Found, but its sign-in state could not be read.
Not installed Not found.
Unavailable Found but not usable: it does not answer, config.json points at a missing file, or it is installed only through npm (a .cmd launcher Cortex does not run). The message says which and what to do.

Each CLI that is not installed has a checkbox, checked by default. Install selected runs, one at a time, each checked CLI's official installer for your Windows user: winget for Claude Code, OpenAI's installer script for Codex, npm for OpenCode (which needs Node.js). While it runs each row shows its progress; Cancel stops the current installer and skips the rest. Afterwards each row says Installed, Already installed — kept, Failed (with the reason, what to do and the command to run by hand, all copyable) or Cancelled; a failed row can be installed again. Cortex never reinstalls, replaces or downgrades a CLI that is already there, never installs over a path set in config.json, and never asks for administrator rights. Installing a CLI gives no account, subscription or credits. Details: installation.

MCP#

Cortex hosts an MCP server (ADR 0008, 0010) so external clients can drive it with the same operations as the window.

  • Server: status Running or Off; the local endpoint http://127.0.0.1:<port>/mcp (default port 47821); the public URL, or "Local only" when mcp.public_url is not set. Status Off means it is disabled in config.json or failed to start (for example the port is in use; see the mcp.start_failed entry in the log).
  • The server exposes 32 tools (the window does not list them): list_projects, list_runtimes, list_agents, get_agent_status, create_agent, update_agent, start_agent, send_message, interrupt_agent, stop_agent, poll_agent_events, create_objective, plan_objective, propose_objective, list_proposals, edit_proposal, approve_proposal, reject_proposal, list_tasks, get_task_status, cancel_task, cancel_objective, pause_objective, resume_objective, reassign_task, approve_task, retry_task, integrate_task, list_skills, post_message, read_messages, ack_message. Agents created over MCP are structured.
  • Local clients authenticate with a user token. It is off until you turn it on in the MCP screen's "Local clients" section, which also has Copy token (the only way to read it) and Regenerate (the old value stops working at once). Whoever has the token acts as you, so turn it on only for clients you run yourself. mcp.json keeps it sealed with Windows DPAPI for your user; a token from an earlier Cortex keeps its value but starts off. Agent sessions get their own credential through CORTEX_MCP_URL and CORTEX_MCP_TOKEN: with it an agent reads the agents, tasks, objectives and proposals of its own project only (another project's read as not found), and talks to the other agents of its project through the message bus (post_message, read_messages, ack_message), never to their processes. A message is untrusted text for its reader and grants no permission. When messages wait for an agent, the next turn Cortex gives it (a task or your input) ends with a one-line notice of how many.
  • Remote access: Cortex does not open a tunnel. If you publish the local port through your own HTTPS tunnel, set mcp.public_url to its origin. A remote client then starts an OAuth flow and a browser page shows a code (format XXXX-XXXX).
  • Authorization requests: each shows the client name, where it returns to, how long ago it asked and the time left (a request expires after 5 minutes). Deny is one click. Approve asks for the code shown in your browser; type it and Confirm. A wrong code leaves the request pending and shows an error under the field. The window never displays the code, so a look-alike request cannot be approved by a click. If more than one request is pending, approve only the one whose code your browser shows. The sidebar MCP item shows the pending count.
  • Connected clients: client, return hosts and authorization time. Revoke asks "Revoke access?" and takes the access away on Confirm revoke.
  • An approved remote client can do everything you can in the window, including creating, starting and instructing agents that execute code on this machine. Approve only clients you started.

Skills#

Lists the skills Cortex finds: the skills folder of the data directory (global, %LOCALAPPDATA%\Cortex\skills by default) and the .cortex\skills folder of each project. A skill is a folder with a skill.json manifest (name, version, description, scope, content and runtimes; an unknown field makes it invalid) and a Markdown file (SKILL.md by default), and nothing else but files: a subfolder or a link inside it makes the skill invalid. A new skill is disabled. The screen reads the folders when it opens; Rescan reads them again.

The table has one row per skill: name and description, scope (global, runtime <id>, project <id>, agent <id>), version, origin (global or the project's name), state (enabled, disabled or changed) and its action:

  • Enable (a disabled skill) approves the version and content shown and starts delivering it to the agents it applies to. If the folder changed since the list was read, Cortex refuses it and reads the list again, so you see the new version.
  • Disable (an enabled skill) stops delivering it. The folder is kept.
  • Approve and Disable (a changed skill, whose files changed after it was enabled): Approve accepts the content as it is now; Disable turns it off without accepting it.

Below the table:

  • Not valid lists the folders that are not skills, with the reason.
  • Conflicts lists skills with the same name. With different scopes, the most specific one is delivered (agent, then project, runtime, global). With the same scope from different folders (ambiguous), none is delivered until you disable one of them. The agents affected are shown.
  • Effective set shows, for the agent you pick, every skill that applies to it and its status: Delivered, Disabled, Changed since enabled, Not written for this runtime, Overridden by, Ambiguous with, Over the limit of 32, or The runtime does not take skills.

Claude Code, Codex and OpenCode take skills. An agent receives an index of its delivered skills (name, version, description and file path) and reads a skill's file when the task matches its description. Cortex does not copy the content, and a skill grants no permission. An agent takes at most 32 skills, within a 12,000-character index. A change applies when an agent starts: a running agent keeps the skills it started with. Design record: ADR 0014 (Portuguese).

8. Configuration#

There is no settings screen. The only configuration is config.json in the data directory. Edit it while Cortex is closed; it is read once at startup. If the file does not exist, Cortex writes one with the defaults on startup. Unknown keys, out-of-range values or invalid JSON stop the Core with config.invalid, naming the field.

Data directory: %LOCALAPPDATA%\Cortex, or the absolute path in the CORTEX_DATA_DIR environment variable (this lets you run a separate instance; Start.bat has a commented line for it).

8.1 Keys#

json
{
  "schema_version": 1,
  "logging": { "level": "info", "max_file_bytes": 5242880, "max_files": 3 },
  "resources": { "max_active_processes": 6 },
  "orchestrator": { "max_parallel_tasks": 2 },
  "mcp": { "enabled": true, "port": 47821 }
}
Key Default Rule
logging.level info error, warn, info, debug or trace.
logging.max_file_bytes 5242880 65536 to 1073741824. Size at which the log rotates.
logging.max_files 3 1 to 20, the active file included.
resources.max_active_processes 6 1 to 32 runtime process trees at once; a start above it fails with resource.limit_reached.
orchestrator.max_parallel_tasks 2 1 to 32.
orchestrator.max_parallel_tasks_per_project none Optional, 1 to 32. Tasks of one project running at once.
orchestrator.max_parallel_tasks_per_runtime none Optional, 1 to 32. Tasks on one runtime running at once.
mcp.enabled true Whether the MCP server starts.
mcp.port 47821 0 (system picks) or 1024 to 65535, on 127.0.0.1.
mcp.public_url none Optional. https://host or https://host:port, no path, query or fragment.
runtimes.<id>.executable none Optional. Absolute path of the CLI, used instead of searching PATH. Ids: claude-code, codex, opencode.

8.2 Runtime executables#

Without runtimes.<id>.executable, Cortex searches its own PATH, then your user and machine PATH as Windows has them now (so a CLI installed while Cortex runs is found without a restart), then each CLI's usual install folder. Claude Code: claude.exe (also %USERPROFILE%\.local\bin from the native installer and winget's links folder). An npm install only gives a .cmd shim, which Cortex does not run; point runtimes.claude-code.executable at the real claude.exe. Codex: codex.exe (also %LOCALAPPDATA%\Programs\OpenAI\Codex\bin from OpenAI's installer; a .cmd is refused). OpenCode: opencode.exe, or the npm global layout next to its opencode.cmd shim, of OpenCode 1 (opencode-ai) or OpenCode 2 (@opencode/cli); OpenCode 2 is recognised only in that npm layout. The full list is in installation; see also ADR 0009 and ADR 0015.

8.3 Files in the data directory#

config.json, projects.json, agents.json, objectives.json, processes.json, mcp.json (secret, sealed), mcp_oauth.json (secret, sealed), transcripts\ (the console lines kept per agent), setup.json (when the first-run setup was finished), cortex.lock, and logs\cortex.log (JSON lines; rotated to cortex.1.log, cortex.2.log, ...). Do not edit the data files while Cortex runs.

9. Visible but not available#

These elements are drawn so the layout is complete. They are greyed, show the tooltip "Not available yet" where they have one, and do nothing.

  • Sidebar items: Context, Resources, Events, Tools (disabled). Agents, Tasks, Processes, Runtimes, MCP, Skills, Hooks and Behaviours open a screen; the Hooks and Behaviours screens are read-only (they list what hooks.json and behaviors.json define, and changing them takes editing those files).
  • Account menu (sidebar footer): name and role are dashes; Account settings, Switch account and Sign out are disabled. Cortex has no accounts.
  • Card front: the "step -" label and its progress bar. Agents search row: the overall progress dash and bar.

10. Not implemented#

Planned (see Plan.md and TODO.md), not built: a command-line interface, clean-machine installation validation and code signing, and the larger control-plane work (context manager, capability registry, spawning and autonomy, observability). Also absent: Linux and macOS support, and removing projects from the window.

11. Limitations#

  • Windows only (see section 1). The installer is per-user and not code-signed.
  • Structured agents cannot edit files or run anything that needs approval: Claude Code runs with prompts denied, Codex with a read-only sandbox, OpenCode with its edit, bash and web fetch permission requests rejected. Use terminal mode (Claude Code only) when you need the CLI's own approval flow.
  • Output is kept in memory (256 KiB per agent) and the last 2,000 lines per agent on disk; sessions themselves do not survive a Cortex restart.
  • A Codex agent runs one process per turn; interrupt ends that process and the next turn resumes the thread.
  • The window shows each runtime's name and model hint from the Core but not its health: a missing CLI appears only when you start the agent.
  • One instruction in the Orchestrator panel always makes one task.

12. Troubleshooting#

Symptom Check Fix
Splash: "Cortex Core could not start", code instance.already_running Look for another Cortex window or cortex-desktop.exe in Task Manager. Close it, or set CORTEX_DATA_DIR to another absolute path to run a second instance.
Splash: config.invalid The message names the field. Open %LOCALAPPDATA%\Cortex\config.json. Fix the field (section 8.1). Deleting the file regenerates the defaults and drops your runtime paths.
Splash: dirs.invalid_data_dir or dirs.unresolved Is CORTEX_DATA_DIR set and absolute? Is %LOCALAPPDATA% defined? Set CORTEX_DATA_DIR to an absolute, writable folder, or unset it.
Start fails with runtime.not_installed The Runtimes screen, or where claude.exe in a terminal. The message says whether the CLI was not found or a configured path does not exist. Install the CLI from the Runtimes screen or by hand, or set runtimes.<id>.executable to its full path (that setting needs a restart of Cortex).
A Runtimes install fails The row's message (it ends with the installer's last line) and its remediation. Fix what it names (winget or Node.js missing, network), then install again, or run the copyable command in a terminal.
Start fails with resource.limit_reached The message gives "N of M runtime processes". The Processes screen shows what is alive. Stop another agent, or raise resources.max_active_processes and restart Cortex.
Agent CRASHED right after opening Cortex, code recovery.cortex_restart Cortex ended abruptly (crash, killed process, incomplete shutdown) while the agent was active. A normal close leaves agents STOPPED. Start it again.
Agent FAILED or CRASHED, runtime.exited_unexpectedly Read the Console output (structured) or the card terminal (terminal mode) for the CLI's own error. Fix the cause the CLI reports, then Start.
Start stays in STARTING A start waits up to 60 s, then fails with the reason shown. Check logs\cortex.log. Press Stop to cancel earlier, then fix the cause and Start.
Send is disabled Tooltip on Send: not started, running a task, or terminal mode. Start the agent; cancel the task; or use the card terminal.
Edit is disabled Tooltip: "Stop the agent to edit it." Stop the agent, then Edit.
Card shows "No terminal session." while READY Is the agent in terminal mode and the Core offering a session? Restart the agent.
Orchestrator field disabled Tooltip names the cause. Add an agent, or select one to pick the project.
Task stays CREATED or READY The Detail column gives the reason. waiting.no_eligible_agent: create a structured agent in that project. waiting.no_available_agent or waiting.agent_unavailable: start an agent. waiting.parallel_limit: wait, or raise orchestrator.max_parallel_tasks. waiting.project_limit or waiting.runtime_limit: wait, or raise orchestrator.max_parallel_tasks_per_project or orchestrator.max_parallel_tasks_per_runtime. waiting.retry_backoff: a retry is scheduled. waiting.dependency_blocked: a task it depends on is BLOCKED; approve, retry or cancel that task. Act as listed, or Cancel the task.
Task RUNNING for too long No timeout exists. Open the agent's Console. Cancel the task.
MCP screen says Off Is mcp.enabled false? Otherwise search logs\cortex.log for mcp.start_failed (for example mcp.bind_failed, port in use). Set mcp.enabled or change mcp.port, then restart Cortex.
MCP approval says the code does not match The code is the one on the browser page that started the connection. Retype it. A request older than 5 minutes is gone: start the connection again.
An error notice shows a correlation ID Search logs\cortex.log for that ID to see the entries behind it. Use the error's remediation line.

Type to search.