Skip to main content

One-file Extensions

The shortest way to add behavior is one package directory. Keep the program logic in normal executables; keep the wiring in one cortexfs.toml:

review-kit/
├── cortexfs.toml
└── bin/
├── review-agent
└── git-summary
schema = "cortexfs.package/v1"
name = "review-kit"
version = "0.1.0"

[[tools]]
name = "git.summary"
run = "bin/git-summary"
description = "Summarize the current Git worktree"
schema = { type = "object" }

[[agents]]
name = "kit_reviewer"
run = "bin/review-agent"
model = "main"
tools = ["git.summary"]
instructions = "Review changes, use the tool when useful, and cite evidence."
parent = "agent:architect"

Install it with one command:

ctx install ./review-kit

ctx install finds cortexfs.toml, hashes every executable, validates the whole package, then publishes each object through the existing atomic object installer. Use --source PATH when the mounted tree is backed by a specific generation, and use --tier user for tools that should only be visible to the current user. Agent objects are system-tier because their runtime socket is host-owned:

ctx install ./review-kit --source /var/lib/cortexfs/storage/current

When a privileged installer is targeting a different user, declare that runtime identity in the package instead of inheriting the installer's root credentials:

[[agents]]
name = "kit_reviewer"
run = "bin/review-agent"

[agents.identity]
uid = 1000
gid = 1000
groups = [1000]

The run file is the extension point. A tool implements the Tool SDK and an agent implements the Agent SDK; both are ordinary executable files, so a Rust, shell, or another host-language build can produce them. An SDK agent receives one hosted envelope on stdin and returns JSONL events. It may yield a tool call; the host performs the capability check and sends the observation back for the next step. This is the custom execution loop, without a resident plugin daemon.

Topology is just the parent edge. Every agent names its parent as agent:NAME (optional session: and run: qualifiers remain available), so a tree is visible in the same control files that enforce ownership:

[[agents]]
name = "planner"
run = "bin/planner"
parent = "agent:architect"

[[agents]]
name = "builder"
run = "bin/builder"
parent = "agent:planner"

The package file is authoring input, not a second /ctx namespace. After installation the durable result is still only agent/<name>.d/*, tool/<name>.d/*, ordinary session files, and the existing sockets. The raw ctx object install command remains available for package builders that need full manifest control; most users do not need to see it.

Refresh is explicit: commit the package or restart the process that consumes the source generation. ctx install never starts a watcher, polling loop, or background plugin service.