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.
For the short interactive path, run ctx in a project directory. It creates a
fresh session with that directory mounted at /workspace and opens chat. Run
ctx resume in the same directory to reopen its session, or pass
ctx resume executor --session SESSION for an explicit session. ctx status is
the explicit status command; ctx help and ctx --help show the CLI help.
Find Available Objects
ctx ls model
ctx ls agent
ctx ls tool
Common object shapes:
/ctx/model/main
/ctx/model/debug/echo
/ctx/agent/executor
/ctx/agent/executor.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, executor, and product-manager.
architect is the root planning and coordination agent; executor and
product-manager use agent:architect as their parent. executor is the
writable implementation and verification role; product-manager is read-only
and turns user needs into measurable acceptance criteria.
agent/main and agent/main.sock alias executor. Retired base, coder,
reviewer, and worker names are leftover objects, not the managed tree.
Those three roles are hosted agents: bootstrap writes an object-runner wrapper
plus system.md. The packaged Agent SDK binaries
cortexfs-agent-architect, cortexfs-agent-executor, and
cortexfs-agent-product-manager are optional executables that print a
role/mission/handoff envelope without calling a model. They are examples and
drop-in run files, not the default /ctx/agent/<name> wrappers. See
One-file Extensions and Internal Architecture.
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, coder, reviewer, and worker 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 executor.d/system.md treats executor as the implementation and
verification agent:
independent implementation work should be a delegated react node in
context/plan.json. A delegated node that omits agent uses executor,
matching the managed reference tree. A node that omits session uses the
current parent session name. The parent policy must still permit
agent:executor create; choosing the default never grants authority.
Explicit agent names remain unchanged. Existing plans naming retired worker
continue to require that object and its matching create permission. Update those
plans to "agent": "executor" when migrating a fresh installation.
Advance one schedule step with:
ctx schedule status home/1000/agent/executor/session/default/context/plan.json --done plan
ctx schedule advance home/1000/agent/executor/session/default/context/plan.json --done plan
ctx schedule claim home/1000/agent/executor/session/default/context/plan.json work-123
ctx schedule result home/1000/agent/executor/session/default/context/plan.json work-123 done "implemented"
ctx agent wait executor 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. list prints the
preset name, auth method, and destination file:
ctx provider preset list
ctx provider preset show google
ctx provider preset install openrouter
ctx provider preset install deepseek
ctx provider preset install compatible --name local --base-url http://127.0.0.1:8317/v1 --model custom-model
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 short names remain openai, anthropic, and google. gemini
aliases google. Additional OpenAI-compatible presets install under their
explicit name. The host-configured GitHub Copilot endpoint uses
github-copilot and accepts copilot as an adapter alias.
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 executor --session default
ctx send executor "Analyze /workspace/assets/screenshot.png and summarize UI issues"
Use explicit mounts when you need tighter visibility:
ctx agent start executor --session image-review \
--no-default-workspace \
--mount "$PWD/assets" /input ro \
--mount "$PWD/docs" /docs ro \
--cwd /docs
ctx send executor --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. A
read-write /workspace keeps ordinary Git metadata writable; CortexFS does not
implicitly over-mount .git read-only. Path-level policy may still make
/workspace/.git read-only. Linked-worktree metadata outside the authorized
workspace needs a separate mount. 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 executor --session default
ctx agent watch executor --session default
ctx agent attach executor --session default
To host an external Agent CLI instead of tsh, pass the exact child after
--. That path is one-shot, may receive a writable /ctx after FUSE
validation, and may receive policy-gated pasta egress. See
Extending CortexFS:
ctx agent start executor --session default -- /usr/bin/codex
The terminal socket lives at:
/ctx/home/<uid>/agent/<agent>/session/<session>/terminal/main.sock
The FUSE-visible path aliases the root-owned
/run/cortexfs/terminal/broker.sock. ctx authenticates the broker and asks
for the named agent/session; it does not connect to legacy per-user terminal
sockets. watch is read-only; attach connects your stdin to the terminal.
Control the sandbox explicitly when needed:
ctx agent start executor --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 executor
agent.sh executor "summarize this repository"
agent.sh --chat executor
agent.sh --attach executor
agent.sh --watch executor
agent.sh --session default executor "inspect the failing test"
agent.sh --resume executor
agent.sh executor opens the chat UI through
ctx agent chat executor --session default. With prompt arguments, it forwards one
message to ctx agent send executor --session default. Use
agent.sh --watch executor to observe the agent terminal, and agent.sh --attach executor only when you want to enter ctxterm -> tsh. agent.sh does not keep a
private chat database.
Compose agents from shell
examples/agent-pipeline.sh composes the current architect, executor, and
product-manager sockets without adding /ctx/workflow, a queue, or a resident
coordinator. Bind every listener to the same host repository before the run;
--cwd names the sandbox path, while the explicit rw mount identifies the
shared host tree:
REPO=$(pwd -P)
for role in architect executor product-manager; do
ctx agent start "$role" --session default \
--no-default-workspace --mount "$REPO" /workspace rw --cwd /workspace
ctx ping "agent/$role"
done
CTX_BIN=ctx ./examples/agent-pipeline.sh \
--max-rounds 2 \
-- "fix the parser and prove the regression test"
The architect plans once. The executor and product-manager then iterate for at
most three explicit implementation/review rounds. Override --coder and
--reviewer when a deployment uses different role names. The reviewer's first
non-empty line is a machine-readable
PASS or CHANGES; PASS exits zero, exhausted CHANGES exits one, and an
invalid verdict exits 65; a failed ctx stage propagates its original exit
status. Before the first send, the script reads each role's existing cwd and mount
controls and aborts unless all three contracts are non-empty and byte-identical;
it never assumes that the shell's current directory reaches an already-running
listener. Every stage uses a durable, caller-owned session name under the
existing agent ABI. The omitted prefix defaults to a fresh timestamp/PID name.
Passing --session-prefix NAME explicitly resumes those durable plan/code/review
sessions when the prefix already exists. Output is never silently used after
truncation: the sink retains at most CTX_PIPELINE_MAX_STAGE_BYTES + 1, drains
the producer to preserve its real exit status, and fails the stage on overflow
without returning a partial result.
Use scripts/agent-pipeline-smoke.sh for the provider-free mock-CLI black-box
test. The build-free hosted agent in examples/extensions/shell-agent/ is a
second onboarding smoke: it implements sdk-envelope-v1 in POSIX shell plus
jq, while CortexFS retains lifecycle, policy, session, and socket authority.
Use the Rust Agent SDK instead when tool continuation or typed host APIs are
needed.
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 executor --session default --cwd /workspace
ctx agent send executor --session default "round one: read the current task"
ctx agent send executor --session default "round two: continue from the previous turn"
ctx agent history executor --session default
ctx agent output executor --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/executor.d/system.md
ctx set agent/executor.d/system.md "You are a careful Rust coding agent."
ctx cat agent/executor.d/prompt.template.md
ctx agent prompt executor
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/executor/session/default/AGENTS.md
cat /ctx/home/$(id -u)/agent/executor/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 executor
ctx agent output executor
ctx agent trajectory executor
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.