Daily Usage
The everyday CortexFS experience should feel like Unix: discover objects, read state, then execute files or connect to sockets when you need work done.
Find Available Objects
ctx ls model
ctx ls agent
ctx ls tool
Common object shapes:
/ctx/model/main
/ctx/model/debug/echo
/ctx/agent/coder
/ctx/agent/coder.sock
/ctx/tool/fs.read
The named file executes work, the matching .sock handles stateful JSONL
interaction, and the matching .d/ directory stores small control files.
On some deployments, /ctx/agent/<name>.sock is an owner-authorized symlink
to a user runtime socket; on some system deployments it may also be a direct
socket node. Treat both as valid implementation forms and probe with nc -U or
readlink according to what the mount currently exposes.
Call A Model Directly
Start with the echo model while debugging:
/ctx/model/debug/echo "hello cortex"
echo "summarize this file" | /ctx/model/main
Change the /ctx/model/main alias when you want a different default model.
Do that by changing the alias instead of adding provider-specific root entries.
The reference tree provides architect, coder, reviewer, and worker.
architect is the root planning and coordination agent; coder, reviewer,
and worker use agent:architect as their parent.
Bootstrap and inspect the reference source with:
ctx bootstrap
ctx bootstrap --check
ctx bootstrap --dry-run
ctx bootstrap writes bin/cortexfs.bootstrap.json only when the schema,
tree version, managed-agent list, or required migrations need refresh. Retired
base and executor objects are reported but retained for
manual review because old installations have no manifest proving ownership and
full control-tree integrity. A successful bootstrap makes the next --check
clean.
The default coder.d/system.md treats coder as the parent integrator:
independent implementation work should be a delegated react node in
context/plan.json, delegated nodes that omit agent use worker, and
delegated nodes that omit session use the current parent session name.
Advance one schedule step with:
ctx schedule status home/1000/agent/coder/session/default/context/plan.json --done plan
ctx schedule advance home/1000/agent/coder/session/default/context/plan.json --done plan
ctx schedule claim home/1000/agent/coder/session/default/context/plan.json work-123
ctx schedule result home/1000/agent/coder/session/default/context/plan.json work-123 done "implemented"
ctx agent wait coder work-123 --session default
status reads the plan, child table, and delegated worker
agent/<name>, agent/<name>.d/model, and life; it does not invent
main/owned defaults when the delegated backing agent is missing, then prints
node<TAB>kind<TAB>agent<TAB>child<TAB>session<TAB>model<TAB>life<TAB>state. advance
materializes ready child handoffs, claim moves a materialized child from
pending to active, and result writes the terminal child result under
context/child/<child>/. Command output includes the parent ref plus the child
agent, session, model, life, handoff.md, result.md, and
refs.jsonl ABI paths so neither parent nor worker has to guess coordination
state. agent wait is a non-blocking waitpid-shaped reader: while the child is
pending or active it fails, and once the child is done, error, or
cancelled it prints
child<TAB>status<TAB>agent<TAB>session<TAB>model<TAB>life followed by
result.md. These commands do not start background listeners, polling loops,
or a second submission entrance.
Provider secrets are not written into model files or .d/ control
directories; provider adapters resolve API keys from provider environment
candidates first (if set), then the CortexFS system secret store
(/var/lib/cortexfs/secrets/provider/<provider>/<slot>). If a required
credential is absent, the model is considered unconfigured.
Install file-based presets for common providers first:
ctx provider preset list
ctx provider preset show google
ctx provider preset install codex
ctx provider preset install openai
ctx provider preset install anthropic
ctx provider preset install google
Provider authentication methods are declared alongside those presets. Inspect the methods without exposing credentials:
ctx provider auth methods codex
The output lists the method, OAuth flow, and logical slot. Credentials remain in
the root-owned secret store; no identity tree is added to /ctx.
The provider library resolves those declarations through one registry. OpenAI
and Codex use the OpenAI-compatible adapter, Claude uses the Anthropic adapter,
and a GitHub Copilot adapter can be registered with a host-owned OAuth client
configuration. Login, device login, refresh, persistence, and model discovery
run through the same adapter boundary and normalized credential/model shapes;
the Agent does not branch on OAuth endpoints or API-key headers. Copilot's
--device login displays its
verification URI and user code, then polls with a bounded timeout.
Host-configured providers can declare an OAuth device block with request,
token, and verification endpoints; this keeps device-code flow provider-neutral
without adding another /ctx namespace.
Canonical provider names are openai, anthropic, and google. codex is
an alias for the openai preset; gemini is an alias for the google preset.
The host-configured GitHub Copilot endpoint uses github-copilot as its
canonical provider name and accepts copilot as an adapter alias.
After installing codex, models are still projected under the canonical
/ctx/model/openai/<model> path. CortexFS does not add a
/ctx/model/codex namespace.
Model proxying is not an agent and is not written into provider JSON. The single global route table is:
/ctx/model/route
This file decides both transport and key slot. Multiple providers, multiple models, and multiple keys for one provider all route through this table:
group(proxy) -> http(http://127.0.0.1:8080/v1), key(office)
group(local-socket) -> unix(/run/user/1000/cortexfs/proxy/openai.sock), key(local)
dip(198.51.100.45) -> direct
# dip(203.0.113.43) -> JP
domain(bestproxy.com) -> proxy
pname(NetworkManager, systemd-resolved, dnsmasq) -> must_direct
dip(geoip:private) -> direct
dip(geoip:cn) -> direct
domain(geosite:cn) -> direct
model(embedding-*) -> local-socket
fallback: proxy
key(office) means another credential slot for the same provider and
selects /var/lib/cortexfs/secrets/provider/<provider>/office.
Without key(...), CortexFS uses the default slot.
Manage Agents
ctx agent is the thin client for the current ABI. Creating, starting, and
stopping agents still goes through ordinary tools or file ABI; it does not add
a workflow entrance:
ctx agent new reviewer --model openai/gpt-5.6 --tool fs.read
ctx agent new reviewer --label reviewer_t --shared project-a:read --mount /work /work ro
ctx agent new --from .cortexfs/agents/reviewer/agent.yaml
ctx agent apply reviewer --from reviewer
ctx agent start reviewer --session default
ctx agent status reviewer
ctx agent ps
ctx agent stop reviewer
Inspect or change the agent's coarse file/shell ceiling with normal Unix tools:
ls -l /ctx/agent/reviewer.d/perm
chmod 400 /ctx/agent/reviewer.d/perm # read tools only
chmod 700 /ctx/agent/reviewer.d/perm # read, write, and shell families
The marker adds a ceiling to existing mount, Linux, agent-policy, and tool-policy checks; it does not replace them.
Host-side agent.yaml files (also agent.yml and agent.json) are
authoring inputs. ctx agent new --from and ctx agent apply --from
validate and materialize them into agent/<name>.d/*; runtime authority
continues to come only from the discrete control files. A short --from NAME
searches .cortexfs/agents and ~/.config/cortexfs/agents.
An Eve project can be used as the same authoring input without installing a Node runtime:
ctx agent new --from ./my-eve-agent
ctx agent apply reviewer --from ./my-eve-agent
The importer reads bounded static agent/instructions.md and a literal
model: "provider/model" from agent/agent.ts. It records the discovered Eve
tools, skills, channels, subagents, and schedules in the agent description, but
does not execute TypeScript, expose secrets, start an HTTP channel, or add a
watcher. Eve capabilities remain source data until an explicitly governed
CortexFS tool is installed and allowed by policy; this keeps the import
reproducible at the Git/process refresh boundary.
schema: cortexfs.agent.profile/v1
name: reviewer
description: code review agent
instructions: Review diffs carefully.
model: openai/gpt-5.6
tools: [fs.read]
parent: agent:architect
ctx agent new prefers /ctx/tool/agent.create; if that tool is absent, host
ctx creates the standard agent/<name>.d/* control files and
home/<uid>/agent/<name>/ skeleton. ctx agent start starts the explicit
runtime; once the terminal socket is reachable it writes
agent/<name>.d/status=ready and appends an agent.start event to
agent/<name>.d/log. ctx agent stop prefers /ctx/tool/agent.stop; if that
tool is absent it writes agent/<name>.d/status=dead, clears pid, and
appends an agent.stop event. ctx agent status and ctx agent ps only read
ordinary agent/<name>.d/* control files. agent status keeps the first line
as the status value, then prints model=..., life=..., parent=...,
children=..., pid=..., uid=..., gid=..., groups=..., root=..., and
cwd=.... children=... counts direct children whose effective state is not
dead; ready or busy children with stale numeric pids are excluded the
same way as ctx agent ps.
Non-default models and non-owned lifecycles are visible in ctx agent ps.
ctx agent env NAME prints the sandbox environment derived by
ctx agent start, and ctx agent children NAME shows parent-side child state
plus the backing worker parent_session, model, life, status, and pid.
AGFS-style service composition uses the existing file ABI rather than another
root namespace: use shared/<space>/data for durable values, the documented
shared/<space>/queue/{inbox,pending,lease,claimed,done,failed} rename protocol
for work, and bounded fs.read, fs.list, fs.stat, and fs.write tools for
inspection and mutation. There is no resident plugin daemon, polling worker,
or heartbeat namespace; commit facts and ordinary session/status files remain
the source of truth.
Submit Images And Other Files
For images, PDFs, audio, archives, or other binary material, submit a path reference instead of putting bytes into the prompt. CortexFS keeps the file itself in workspace or shared space visible to the agent; the conversation only describes the task and the path.
When you start an agent from the current directory, that directory is mounted as
/workspace by default:
ctx agent start coder --session default
ctx send coder "Analyze /workspace/assets/screenshot.png and summarize UI issues"
Use explicit mounts when you need tighter visibility:
ctx agent start coder --session image-review \
--no-default-workspace \
--mount "$PWD/assets" /input ro \
--mount "$PWD/docs" /docs ro \
--cwd /docs
ctx send coder --session image-review "Inspect /input/screenshot.png and use /docs/DESIGN.md"
Use shared space when multiple agents or sessions need the same material:
mkdir -p "$(ctx path shared project-a)/input"
cp screenshot.png "$(ctx path shared project-a)/input/"
ctx agent new reviewer --shared project-a:read
ctx send reviewer "Inspect /ctx/shared/project-a/input/screenshot.png"
This keeps large files out of message history. Context records paths, summaries, and refs; reading image bytes, extracting text, rendering thumbnails, or calling a vision model happens lazily through a visible tool.
Watch And Attach Terminals
ctx agent start mounts the caller's current directory at /workspace inside
the sandbox by default, then starts ctxterm -> tsh from /workspace. If the
caller directory contains .git, .git is additionally over-mounted read-only
at /workspace/.git. The agent's HOME is the sandbox's own /home/agent, so
shell configuration and caches are not written into the project directory:
ctx agent start coder --session default
ctx agent watch coder --session default
ctx agent attach coder --session default
The terminal socket lives at:
/ctx/home/<uid>/agent/<agent>/session/<session>/terminal/main.sock
The FUSE-visible path may be a symlink to
/run/user/<uid>/cortexfs/terminal/.../main.sock; older installs may also
point to /run/cortexfs/terminal/.../main.sock. watch is read-only; attach
connects your stdin to the terminal.
Control the sandbox explicitly when needed:
ctx agent start coder --session review \
--no-default-workspace \
--mount "$PWD" /workspace rw \
--mount "$PWD/docs" /docs ro \
--cwd /workspace
Use The Tool Shell
tsh is the CortexFS tool shell, not a host shell. Standalone human tsh
resolves commands in this order:
1. CTX_HOME/.tshrc line CTX_PATH=...
2. process CTX_PATH
3. default /ctx/tool:/ctx/home/<uid>/tool
Inside an agent terminal, tsh uses the process CTX_PATH that the agent
runtime derives from policy, mounts, and uid/gid. User .tshrc does not
override that authorization path.
.tshrc is a data file, not shell syntax:
CTX_PATH=/ctx/tool:/ctx/home/1000/tool
Useful checks:
tsh --list
tsh which fs.read
tsh help fs.read
When invoking tools directly, prefer doing it from the agent terminal through
tsh, so CortexFS can apply agent policy, mounts, uid/gid, and CTX_PATH
together.
Agents with the agent.update grant can iterate themselves: the tool
atomically replaces the calling agent's own system.md or
prompt.template.md through the host-validated run capability socket, and the
new prompt applies from the next run. Other agent controls stay host-owned;
see docs/spec/tool-policy-abi.md for the exact contract.
Use agent.sh
The repository still includes agent.sh as a shell frontend:
install -m 0755 agent.sh/agent.sh ~/.local/bin/agent.sh
agent.sh --help
agent.sh coder
agent.sh coder "summarize this repository"
agent.sh --chat coder
agent.sh --attach coder
agent.sh --watch coder
agent.sh --session default coder "inspect the failing test"
agent.sh --resume coder
agent.sh coder opens the chat UI through
ctx agent chat coder --session default. With prompt arguments, it forwards one
message to ctx agent send coder --session default. Use
agent.sh --watch coder to observe the agent terminal, and agent.sh --attach coder only when you want to enter ctxterm -> tsh. agent.sh does not keep a
private chat database.
Installed Multi-Turn Smoke
After installation, the minimal multi-turn smoke should use the existing session ABI instead of adding a test entrance:
ctx bootstrap
ctx agent start coder --session default --cwd /workspace
ctx agent send coder --session default "round one: read the current task"
ctx agent send coder --session default "round two: continue from the previous turn"
ctx agent history coder --session default
ctx agent output coder --session default
This path checks agent/<agent>.sock, messages.jsonl, latest.md, current
session selection, and prompt-history injection. Durable conversation facts
stay in /ctx/home/<uid>/agent/<agent>/session/<session>/messages.jsonl;
ctx agent prompt is only for inspecting the prompt that would be sent to the
model, not a substitute for a live socket conversation.
When handing independent implementation work to the spark worker, the parent
first materializes the handoff with ctx schedule advance, then gives the
worker the emitted model=, life=, plan=, handoff=, result=, and
refs= fields. The worker writes back through the same
ctx schedule claim/result path; do not add a queue, poller, or second
coordination file.
Customize Agents
User-editable system prompts live at:
/ctx/agent/<agent>.d/system.md
/ctx/agent/<agent>.d/prompt.template.md
For example:
ctx cat agent/coder.d/system.md
ctx set agent/coder.d/system.md "You are a careful Rust coding agent."
ctx cat agent/coder.d/prompt.template.md
ctx agent prompt coder
system.md only defines persona and working style. prompt.template.md
defines how that content is combined with rules, skill metadata, tool
injection, history context, and the runtime contract into the first system
message visible to the model. Template variables include {{agent}},
{{current_time_unix}}, {{agent_instructions}}, {{rules}}, {{skills}},
{{tool_injection}}, {{history_messages}}, and {{runtime_contract}}.
ctx agent prompt <agent> prints the runtime system prompt that CortexFS can
currently render. Use it to inspect the template, agent instructions,
discoverable AGENTS.md rules, bounded skill metadata, and runtime contract. At
real model-call time, tool injection and history context are still filled by
the runtime according to the context window.
The skill list only injects name, description, and the SKILL.md path.
Full SKILL.md content is read only after a skill is selected. Skill metadata
may use at most 2% of the context window; when the window size is unknown, the
hard cap is 8,000 characters. Over budget, descriptions are shortened first;
if still over budget, some skills are omitted and the prompt includes a
warning.
When an agent run builds its prompt, CortexFS writes a best-effort load
snapshot into that agent's private session directory (same text as
{{rules}} / {{skills}}; snapshot write never blocks the run):
cat /ctx/home/$(id -u)/agent/coder/session/default/AGENTS.md
cat /ctx/home/$(id -u)/agent/coder/session/default/SKILLS.md
AGENTS.md: effective merged rules (global + project layers)SKILLS.md: skill metadata only (name/description/path), not fullSKILL.mdbodies
These prompt files do not grant authority. The default native tool remains
tsh; other tools must be discovered, loaded, pinned, and called through
tsh. Effective authority is still decided by agent/<agent>.d/policy,
path, mount, Linux uid/gid, and mode bits.
Use Shared Space
Shared space is an ordinary file directory. Use it for project material, task input, and results exchanged between agents:
ctx path shared project-a
cd "$(ctx path shared project-a)"
Whether an agent can read or write a shared directory is decided by its view, mounts, policy, Linux uid/gid, and mode bits.
Inspect History
ctx agent history coder
ctx agent output coder
ctx agent trajectory coder
Without --session, these commands use session/index/current first and fall
back to default. That means inspecting the current/latest session does not
need a separate latest subcommand.
The underlying history lives at:
/ctx/home/<uid>/agent/<agent>/session/
Raw history is durable fact; context is a rebuildable working set. Compacting
context must not destroy raw messages.
ctx agent trajectory validates and prints an ATIF JSON projection of the
selected session's messages.jsonl and events.jsonl. Tool calls,
observations, and usage remain associated by run and call id; the command does
not create a second history store.