A desktop workspace for one lead agent and many workers. The application uses Codex app-server for model sessions, tools, and permissions. It adds durable orchestration, agent messages, command monitors, and user replies.
This repository owns the application, command tools, tests, and runtime prompts. Its project-local codex-workspace skill describes managed tools and application workflows. No external skill repository is required. Standard Codex CLI delegation belongs to the independent native agent skill, not this application skill.
In the left sidebar, open a project's menu and select New team to group independent chats. Select at least two chats from that project. Each chat keeps its own tasks, history, and subagents. Team members can discover each other and send explicit private messages. Broadcasts and automatic results stay within each chat's original agent tree. The team menu supports edits and dissolution. Drag a chat onto a team to join or move between teams. Drop it onto the project name to leave. A team dissolves when fewer than two chats remain. Dissolution preserves the chats and saved messages but removes peer access.
Select New shared chat to create one conversation with two agents. Choose a project and each participant's account and model before creation. The sidebar shows one chat. No existing chats or peer team are required. Both agents receive the shared messages and reply in sequence. Each agent keeps its own account, model, and context. Independent work stays outside this chat. Select Both agents for one reply each, or select one participant. Discuss (4 replies) gives each agent two turns. Reply next selects the next speaker. Stop ends the exchange and interrupts only its current reply. A new message replaces the remaining reply order after the current reply ends. The exchange waits for answers to agent questions. Personal chat instructions must use the queue while that agent gives a shared reply. Existing two-member teams can also open a shared chat from their menu. That history stays with its original members when the team changes.
Managed workers can use a different provider from their parent. The default is
gpt-6-luna with high reasoning. The orchestrator selects each worker's model
and reasoning level through orchestration_spawn. Studio selects an available
account for that model, preferring the parent's account, then the application
default. account_key selects a specific account. Model and account validation
finish before any worker in the batch is created. Existing worker settings stay
unchanged when the parent chat moves to another account or provider.
Requirements: Python 3.11 or later, Node.js 22.15 or later, and the signed-in Codex CLI. The desktop package currently targets macOS on Apple silicon.
From this repository:
python3 scripts/install-cli.py
npm --prefix web ci
npm --prefix web run build
npm --prefix desktop ci
(cd scripts/claude_bridge && npm --prefix . ci --ignore-scripts --omit=optional)
npm --prefix desktop startClaude Code is also supported through the installed CLI and its Claude subscription.
Run claude auth login, then select Claude Code in the account menu for a new
chat. Use Find existing accounts in Accounts if it does not appear. Studio
reads the model list from Claude Code and keeps credentials in its native store.
It uses the Claude Agent SDK with the installed executable, as in
T3 Code. No Anthropic API key is required.
Claude chats support live Steer, an explicit message queue, native tools, background tasks, questions, action approvals, and Studio agent tools. Limits shows five-hour, weekly, and model-specific subscription windows. The account menu shows the remaining weekly allowance.
Chat settings includes Claude permission modes, extended thinking, automatic compaction, native commands and skills, and context rollback. Model, effort, and fast-mode controls use the native model catalog. A proposed plan waits for a separate implementation request. Rollback preserves the original saved history. Commands and rollback retain their request identities after a lost response.
Accounts includes Claude profiles with separate executable and configuration paths, custom models, launch options, and compaction limits. Sign in with the native CLI before adding a profile. Active sessions keep their current connection; profile changes apply when that connection is idle. For an expired Claude session, select Sign in again on its account in Accounts. Studio opens the native sign-in flow for that profile. Open the sign-in link, then paste the confirmation code in Studio. Use the displayed account email. Studio checks the account identity before it reports success. It does not resend failed chat messages.
Codex model settings include a separate Daybreak switch. Studio checks the
selected account's native model grants before it enables the mode. A change
during an active turn applies to the next turn. Subagent defaults have their
own switch. Account transfers preserve the mode only when the destination
supports it; a provider change clears it. Native review/start cannot select
Daybreak, so use a review task in the chat when this mode is required.
Studio checks installed Codex executables every minute, including CODEX_BIN,
PATH, and the copy bundled with ChatGPT. It checks the protocol schema and runs
an isolated native smoke test without account credentials or model requests.
The newest compatible version becomes an immutable bundle under the state
directory. The bundle includes codex and codex-code-mode-host, with separate
file hashes and one bundle identity. Studio publishes it only after both
executables pass their checks. A failed check preserves the last approved version.
Studio replaces an account app-server only after local and native checks confirm
that no turns, commands, queues, approvals, or unresolved requests remain.
Active work continues on its existing process. Accounts shows versions, pending
updates, and rejection reasons. Studio does not download or install Codex packages.
Studio reads Codex model metadata through a short-lived process of the same approved executable. The reader uses the selected account's native credentials and starts no model tasks. Model grants remain cached for five minutes.
Claude Code uses its native permission rules for its tools. Studio command monitors use the installed Codex command executor with the Studio sandbox policy. This executor does not start model sessions or use account credentials. Monitors support output, terminal input, resize, cancellation, and timeouts. Voice remains unavailable for Claude. Files remain native attachments or file references.
Existing chats can move between Codex and Claude accounts. The chat keeps its identity and displayed history. Subagents stay on their current accounts. A transfer involving Claude creates a destination session with recent text and a path to the complete saved history. It preserves the original native session and does not replay old commands. A provider change selects the destination model and clears queued settings for the previous provider. Codex account transfers continue to use native history copies. See the parity checks for evidence and the tested reference revision.
The command installer creates links in ~/.local/bin. Add that directory to PATH
if your shell does not include it. Use --bin-dir for another directory.
It refuses to replace unrelated files or links. To update links from the old
checkout, pass --replace-from /path/to/previous-checkout.
For browser tasks, Studio uses the installed OpenAI Chrome plugin by default.
Set up the ChatGPT browser extension and browser runtime in ChatGPT Desktop first.
Studio registers the installed Chrome skill with native skills/extraRoots/set.
It passes the browser runtime to native thread/start and thread/resume. Codex
advertises the skill with its path and exposes MCP tools to leads and workers.
Studio does not copy skill text, browser code, or another account’s marketplace.
Each account keeps its own credentials and browser turn history. Explicit plugin
or MCP disable settings and custom runtime commands remain in effect.
Already loaded threads can retain their previous browser runtime. To reconnect an
idle session, unsubscribe and resume that same native thread with the current
configuration. A resume while still subscribed can ignore changed settings.
Active work is not interrupted. Browser website permissions remain native.
Studio detects native Chrome discovery failures and makes one automatic recovery
at an idle turn boundary. It waits for active commands and monitors, preserves
the native thread, and sends a read-only verification instruction. It never
replays a browser action. A failed probe or unknown reconnect response stops
automatic retries; exact request IDs remain in the session recovery record.
For browser access, run codex-canvas and open http://127.0.0.1:4620.
Use codex-control list to inspect the same runtime from a terminal.
Run npm --prefix desktop run package to build the desktop application.
Closing the window preserves the server and its active work. Backend source identity remains available to diagnostics without a persistent notice in chats. Reviewed live patches apply in the background without a backend restart. See live updates for publication and verification.
The packaged macOS application restores its backend after login or a process failure. Saved input and verified interrupted work recover automatically. See restart recovery for the exact behavior and limits.
The mobile layout shows orchestrator chats, team agents, existing projects, account selection, and chat settings. Add the page to the iPhone home screen for a standalone window. The Mac remains the server. SQLite remains the authoritative store.
After the source update, restart Studio when active tasks and monitors finish. Do not stop active work for this update. Then run:
python3 scripts/codex-mobile.pyThe command checks the server version and enables private HTTPS through
Tailscale Serve.
It prints the address for Safari. Connect Tailscale on both devices first.
If Tailscale requests HTTPS setup, complete that setup and run the command again.
Existing unrelated Serve configurations require manual setup.
The server accepts the exact origin in remote-access.json in its state directory.
Set enabled to false there to revoke remote access without a restart.
Tailscale access rules control who can open Studio. Studio adds no separate login.
RxDB replicates SQLite projections to IndexedDB. It keeps message identities across reloads and retries. Different browser drafts remain separate and can be combined. A lost response does not authorize another underlying command. After one complete online load, the browser can cache the interface for later use without the Mac connection. Cached chats and drafts can open while the Mac is unavailable. Browser storage must still contain that data. Text messages for existing chats enter a local queue before the composer clears. The queue retries the same message identity when Studio can reach the Mac again. New chats, new file uploads, and voice require the Mac connection. Return to Studio to resume sync and delivery. Delivery while iOS suspends Studio is not guaranteed. Keep the page open for voice.
The chat snapshot excludes work result histories. The work view loads those histories through its existing API. Mobile sync uses one shared event stream. While Studio is visible, it prepares unarchived chats and the selected team's agent chats in the background. It updates these saved histories before selection. The current chat loads first. At most two background histories load at once. A ready history appears immediately on selection, including its saved scroll position. After a network change or a return to Studio, sync replaces the old connection. A cached workspace cannot send drafts to a different workspace before verification.
Run npm --prefix web run test:mobile for the mobile regression suite.
Set BROWSER=webkit for the WebKit lifecycle and delivery checks.
The performance fixture uses Chromium network and CPU controls in either run.
These checks do not replace a test on a physical iPhone.
Run npm --prefix web run test:responsiveness for the draft and transcript checks.
The final fixture measures the production UI with 301 messages and a CPU slowdown of four.
See the measurement report for results and limits.
Start voice inside the selected chat. Native Codex voice uses that chat's
ChatGPT account through its app-server. No separate API key is required.
Voice can pass spoken tasks directly to the orchestrator. It does not wait for
a separate Send transcript button. Normal orchestrator replies return to voice.
End voice stops the microphone and voice connection. It does not stop the task.
Transcripts remain on the Mac until the chat is deleted. Old courier drafts
remain available for recovery; Studio does not automatically send them.
orchestration_speak supplies additional speakable context to native voice.
Its receipt does not confirm exact audible playback. Use chat buttons for
permission requests. Lock-screen and background voice are not supported.
Existing loaded threads need the realtime feature. Studio enables it by reloading only an idle lead without background commands. Active threads remain running; start voice again after their current work finishes.
| Path | Contents |
|---|---|
web/ |
React, TypeScript, Mantine, Vite |
desktop/ |
Electron host, native bridge, package tools |
scripts/ |
Python server and command tools |
prompts/ |
Runtime worker instructions |
tests/ |
Backend, protocol, browser, and process contracts |
- Orchestration: managed agents, messages, monitors, and state.
- Command guide: waves, steering, and CLI usage.
- Web development: client structure and browser checks.
- Desktop: native boundaries, launch, and packaging.
- Accounts: account selection, profile discovery, and isolation.
- Time awareness: native time reminders and cache evidence.
- Context analytics: response tokens, tool payloads, history, and measurement limits.
- Extraction record: source history and local migration checks.
Use Rename project to change the project label. The directory path stays the same. Use New folder and New subfolder to add folders for chats. Use Move to folder in the chat menu. These folders exist only in Studio. A chat keeps its directory and account.
Each project has one default account. Use Project account in the project menu to select it on desktop or mobile. New chats use that account. Existing chats keep their native account identity. An empty chat can use any available account. Models can use files and skills outside the project directory. Native sandbox and approval settings still apply.
Open Messages in the chat header on a computer or phone.
- For you opens first. It contains questions, permissions, your tasks, and messages from the main agent.
- Team contains To orchestrator, Team broadcast, and Between agents.
Agents can exchange messages and read agent conversations within their agent tree.
An agent tree contains one lead and its workers, with the same rootId.
Independent chats in a sidebar team can also exchange private messages.
Each chat keeps its own work, subagents, and automatic results.
You can still read historical conversations between teams.
Use Multi agent / Single agent in the chat header to change delegation immediately. Single agent prevents new delegation. Existing subagents finish accepted work and report to the main agent. The mode remains saved after a reload or restart. The main agent's model selector includes every available model from the selected account's app-server catalog.
The main agent has the orchestrator role. Subagents ask it for help. Only the main agent sends conversational messages or tasks to you. Native tool permissions still require your approval.
Use a stable request_id with orchestration_send to recover a lost reply.
An exact retry returns the saved receipt without another instruction.
Worker recovery reconciles saved read and validation failures before archive checks.
Unknown mutations still block archive. Tool history and files remain available.
Team status includes the configured concurrency and each queued agent's current blockers.
Messages replace the separate Inbox, Agent chats, and Complaint book screens.
The main conversation and its draft stay open.
You can close a reply and return to its draft.
Requests for user action appear as messages. Reply in the same conversation.
Saved user tasks retain their original dates and replies as messages.
Each message shows its send date and time. There is no separate user task board.
The harness reads the repository's codex-orchestrator or codex-subagent skill
from the server's isLead identity. It adds that skill to the native thread
instructions. Existing threads receive it on their next turn. The versioned turn
context repeats it after a skill change or context compaction.
Workers ask their lead to contact the user. Workers cannot send spoken responses to the user.
Team shows subagent status and opens subagent chats. Back to main agent returns to the main agent. The sidebar and Team panel can collapse at any window width.
Chat settings contains the account, project, model, permissions, and appearance. Appearance supports System, Light, and Dark. Chat actions contains agent tasks, your tasks, changes, plan, rules, search, and background tasks. Search chats searches full history. Filter projects and chats filters the sidebar list. The search control above the transcript searches the current chat. Edit and Another answer prepare a draft in a new branch. They do not send it automatically.
On a phone, Add project opens the server's folder list. The first New chat opens this list when no project exists. Plan shows only the plan reported by the agent. Use Change plan in chat to send instructions. Historical saved plan text remains in storage.
Existing chats, receipts, and agent state remain in
~/.local/state/codex-agents/canvas.sqlite3. Source extraction does not move state.
CODEX_AGENTS_STATE_DIR and CODEX_HOME retain their meanings.
Historical Canvas positions remain in each browser profile. Message drafts remain available.
Closing Electron leaves the backend active.
Run checks for the changed area. These commands use isolated fixtures:
node tests/portable-smoke.mjs
node tests/state-contract-smoke.mjs
python3 -B tests/daemon-contract.py
python3 -B tests/runtime-contract.py
python3 -B tests/role-skills-contract.py
python3 -B tests/turn-start-contract.py
python3 -B tests/prepare-steer-contract.py
python3 -B tests/monitor-lifecycle-contract.py
python3 -B tests/harness-response-contract.py
python3 -B tests/protocol-reader-contract.py
python3 -B tests/catalog-recovery-contract.py
python3 -B tests/native-binary-contract.py
python3 -B tests/native-runtime-updates-contract.py
python3 -B tests/model-catalog-reader-contract.py
python3 -B tests/tool-request-contract.py
python3 -B tests/spawn-request-recovery-contract.py
python3 -B tests/tool-request-http-contract.py
python3 -B tests/control-requests-contract.py
python3 -B tests/task-completion-recovery-contract.py
python3 -B tests/analytics-contract.py
python3 -B tests/analytics-history-contract.py
python3 -B tests/accounts-contract.py
python3 -B tests/runtime-accounts-contract.py
python3 -B tests/limits-refresh-contract.py
python3 -B tests/canvas-contract.py
python3 -B tests/install-cli-contract.py
python3 -B tests/live-updates-contract.py
python3 -B tests/source-contract.py
python3 -B tests/worker-overview-contract.py
python3 -B tests/turn-history-contract.py
python3 -B tests/question-history-contract.py
npm --prefix web test
npm --prefix desktop testBrowser checks use the installed Chrome, or CHROME_BIN. Desktop checks use hidden
Electron windows. Native protocol fixtures can run without paid model requests.
Read each test before running a check that uses the live Codex service.