Research workflows
Run and continue remote Codex tasks
Start a bounded CLI agent task, retain its continuation identifier, inspect sessions, and interrupt a selected task.
Review research files with a remote Codex session
Run a bounded review in a CoCalc project, retain its session identity, ask a follow-up, and inspect or interrupt a running turn. The CLI runs the agent in the selected project without requiring an open browser tab. Save the completed responses locally using the commands below.
You need the CLI quickstart, a project you can use, and a configured Codex authentication/payment source. Run the Bash commands below on your own computer using your account profile. Do not save your personal account login in a shared project.
Check access and prepare a bounded input
export CLI_PROFILE=cocalc-ai
export PROJECT_ID='REPLACE_WITH_FULL_PROJECT_ID'
export CODEX_DIR='/home/user/research-codex-demo'
cocalc --profile "$CLI_PROFILE" --json auth status --check
cocalc --profile "$CLI_PROFILE" project get --project "$PROJECT_ID"
cocalc --profile "$CLI_PROFILE" --json project codex auth status \
--project "$PROJECT_ID"
cocalc project codex exec --help
LOCAL_CODEX=$(mktemp -d)
cd "$LOCAL_CODEX"
cat > analysis-note.md <<'MARKDOWN'
# Analysis for review
Input measurements: 2, 4, 6, 8.
Claim: their arithmetic mean is 5.
Reproducibility note: record the input checksum and Python version.
MARKDOWN
cocalc --profile "$CLI_PROFILE" project file put --project "$PROJECT_ID" \
analysis-note.md "$CODEX_DIR/analysis-note.md"
Adjust /home/user for your project and use a previously unused scratch path.
The Codex authentication result includes data.payment_source,
data.has_subscription, and indicators for configured account, project, or site
API keys. CLI account authentication and Codex authentication are separate:
a successful auth status --check does not establish a usable Codex source.
If the source is none, configure the intended source before running a turn.
For an account using a ChatGPT subscription, the CLI provides the interactive
project codex auth subscription login --project "$PROJECT_ID" flow. Complete
its displayed device authorization yourself, then check status again. Never put
an API key or authentication JSON into a prompt or research file.
Run a read-only first turn
cocalc --profile "$CLI_PROFILE" --timeout 10m --json project codex exec \
--project "$PROJECT_ID" --workdir "$CODEX_DIR" --session-mode read-only \
'Read only analysis-note.md in this directory. Check the arithmetic and identify one missing reproducibility detail. Do not edit files.' \
> codex-turn-1.json
python3 - <<'PYTHON'
import json
from pathlib import Path
response = json.loads(Path("codex-turn-1.json").read_text())
assert response["ok"], response
result = response["data"]
assert result["thread_id"], "No returned thread ID; inspect the response"
Path("codex-session-id.txt").write_text(result["thread_id"] + "\n")
print(result["final_response"])
print("Saved session ID:", result["thread_id"])
PYTHON
export CODEX_SESSION_ID=$(cat codex-session-id.txt)
The expected outcome is an explanation that the mean is 5 and a reproducibility
suggestion. The agent's wording varies; independently check its conclusions.
--workdir is the working directory inside the project. --session-mode read-only requests a read-only session; use synthetic inputs when learning the
workflow and review the selected project before granting write access.
Use data.thread_id from the completed first turn as the continuation ID.
data.session_id echoes the ID you supplied and is null when the first command
omits --session-id. These fields are not interchangeable on that first result.
The JSON result also includes final_response, usage when available, and stream
counters; it is not a transcript of every event.
Continue the same session
cocalc --profile "$CLI_PROFILE" --timeout 10m --json project codex exec \
--project "$PROJECT_ID" --workdir "$CODEX_DIR" --session-mode read-only \
--session-id "$CODEX_SESSION_ID" \
'Based on that review, propose a two-item verification checklist. Do not edit files.' \
> codex-turn-2.json
python3 - <<'PYTHON'
import json
from pathlib import Path
response = json.loads(Path("codex-turn-2.json").read_text())
assert response["ok"], response
print(response["data"]["final_response"])
PYTHON
Keep the same project and save each completed response. Reusing the ID asks CoCalc to resume the Codex session; it does not mean every file remains unchanged between turns. If resuming fails, inspect the error and existing session before choosing to start a new session without that ID. Starting anew loses the prior conversation context.
Choose one output format
Flags on project codex exec |
What is written |
|---|---|
| No output flags | Final response in human-readable output. |
--stream |
Progress on stderr while the turn runs, then the normal result. |
Global --json without streaming |
One result envelope on stdout; parse data. |
--jsonl without global --json |
Raw stream-message JSON objects, one per line on stdout; no final result object. |
Global --json with --stream |
Stream messages followed by the final result envelope on stdout; not one JSON document. |
For scripts like the examples above, use plain --json and wait for the result.
For interactive progress, use --stream. If you choose JSONL, handle each
message by its type; a summary message carries threadId and finalResponse.
Do not feed a streaming output file directly to json.load() as though it were
one result. Avoid combining --jsonl with global JSON output in these recipes.
Inspect or interrupt a running turn
Open a second local terminal while a turn is running. Set the same profile and project ID, then inspect your own recent sessions:
export CLI_PROFILE=cocalc-ai
export PROJECT_ID='REPLACE_WITH_FULL_PROJECT_ID'
cocalc --profile "$CLI_PROFILE" --json codex sessions \
--active --project "$PROJECT_ID"
cocalc --profile "$CLI_PROFILE" --json codex sessions \
--recent --project "$PROJECT_ID" --limit 20
The JSON data is a list of session records. Match the full project ID and
session ID, and inspect state, terminal, updated_at, error, and
session_key. Human output groups turns and shortens IDs, so use JSON to select
an exact target. Listing sessions provides status and identifiers, not their
full conversation transcripts.
To stop one specific active record, copy its full session_key and run:
export SESSION_KEY='REPLACE_WITH_EXACT_SESSION_KEY_FROM_THE_LIST'
cocalc --profile "$CLI_PROFILE" --json codex interrupt "$SESSION_KEY" \
--note 'Stopping the scratch research review'
Alternatively, the interrupt command accepts session:<session_id> or
op:<op_id>. Do not pass an unprefixed session ID when you intend the session-ID
form: an unprefixed value is interpreted as a session key. This command is
cocalc codex interrupt, not cocalc project codex interrupt.
Inspect both the outer ok and the returned data.ok, data.state,
data.terminal, and data.message. Run the session listing again to verify
whether the turn has reached a terminal state. An interrupt request can return
an uncertain result; it is not evidence that all work has already stopped.
Avoid interrupt-all when your goal is to stop only this exercise.
Handle failures and finish
- If a turn times out or ends before its summary, inspect active sessions before sending the prompt again. The remote operation may still be running. Retrying without checking can start additional work.
- If the provider authentication or payment source fails, check the project Codex auth status and resolve that source. Switching the CLI account profile alone does not fix provider authentication.
- If the working directory or file is missing, inspect the project files and
correct the path.
--workdirdoes not upload your local directory. - A notebook-tool transport timeout does not by itself show that the kernel stopped. Check the notebook directly and, if appropriate, run a small read-only cell before restarting anything. Retain the exact failed command and error for support; manually running code can let work continue without repairing the agent connection. See notebook workflows.
- If the agent reports success, verify the research claim yourself. For write sessions, also inspect the file changes before accepting the result.
Retain the session ID and local result files with your research notes. After confirming no scratch turn remains active, delete the scratch input directory through Files if it is no longer useful. The session-control commands above do not delete conversation history or undo file changes.