Agent
The agent is a chat app with tools. It talks to any endpoint that speaks the Anthropic messages API, and it stores every conversation as a .sss file.
Models
Every model you want to use is one .env file in dox-data/agent/models/:
dox-data/agent/models/
deepseek.env url=https://api.deepseek.com/anthropic
key=sk-…
model=deepseek-flash
mify-claude.env url=https://api.llm.mioffice.cn/anthropic
key=sk-…
model=ppio/anthropic/claude-opus-5-5
label=Claude
The filename is the id. url, key and model are required; label is optional and defaults to the id. Lines starting with # and blank lines are ignored, and export prefixes are tolerated.
Two optional keys exist for gateways that behave differently:
| Key | Effect |
|---|---|
reasoning_effort=none |
Passed through to the endpoint. Some OpenAI-compatible gateways require it alongside tools. |
tools=false |
Send no tools at all; the model can only answer, not act. Use it for endpoints that reject function calling. |
One file per model, on purpose: adding a model is creating a file, a broken file only costs that one model, and an env config from another tool can be dropped straight into the directory.
dox-data/agent/config.json holds the shared settings: defaultModel and workspace — the default cwd, i.e. where commands run when nothing else says otherwise. It is not a project binding: the agent can read, write and run anywhere by absolute path.
Two reasons for the indirection:
- Keys live in these files, never in a session. Rotate once, all sessions follow.
- A session only records an id (
"model": "mify-claude"), so a.ssscan be shared without leaking a key.
Which configuration a turn uses
model = request override → session.model → config.defaultModel → first file
baseUrl = that model's url
apiKey = that model's key
model name = that model's model
cwd = bash tool's `cwd` argument → config.workspace
There is no per-session working directory either. A conversation is not tied to a project; a single bash call can point somewhere else with cwd, and file tools accept absolute paths.
That is what makes an agent team possible: three windows, three sessions, three models, all at once.
In the UI
- The toolbar has a model dropdown. Changing it pins the choice into the current session.
- ⚙ opens the model manager: add, edit or delete entries, pick the default, set the default working directory.
There is no SDK. The client is a fetch to ${baseUrl}/v1/messages, which is why any compatible provider works: create a model file with a different url and model.
Tools
| Tool | What it does |
|---|---|
bash |
Runs a shell command and returns stdout/stderr; optional cwd to run elsewhere |
read_file |
Reads a file; images come back as image blocks so the model can see them |
write_file |
Writes a whole file |
edit_file |
Replaces an exact string in a file |
glob |
Finds files by pattern |
grep |
Searches file contents |
web_fetch |
Fetches a URL and returns readable text |
web_search |
Searches the web |
Tools are declared on every request rather than stored with the session — see Sessions. A turn that calls tools looks like this:
model → tool_use → tool_result → model → … → done
Each step streams back as it happens, so a bash command that takes ten seconds still shows the model's reasoning before it finishes.
Interrupting
Ctrl / Cmd + C aborts the running turn. The connection closes, the server aborts the request, and a bash child process is killed rather than left running.
/stop is the same thing for touch devices.
Slash commands
| Input | Effect |
|---|---|
/stop |
Abort the current turn |
/ <command> |
Run a shell command directly, without involving the model |
The second one is the fast path for something you already know how to do: / ls app/ returns the output immediately, no tokens spent.
Images
Paste or drop an image into the composer. It is sent as a base64 image block alongside your text. read_file does the same on the way back, which is what lets the model "see" a screenshot or an SVG.
Sessions
Every conversation is a file under dox-data/agent/sessions/. The agent resumes by path: paste a path into the address bar, or double-click a .sss row in the explorer. Format, sharing and migration are in Sessions.
The TUI
The same agent runs in a terminal, with no browser, no dox, and no node_modules:
node app/agent/tui/main.ts
It reads the same dox-data/, so a conversation started in the GUI opens in the TUI and vice versa.
| Command | Effect |
|---|---|
| (any text) | Send a message |
/stop |
Interrupt the running turn |
/ <command> |
Run a shell command directly |
/model [id] |
Show or set the session's model |
/open <path> |
Open a session by path |
/new [path] |
Start a new session |
/list |
List sessions |
/rename <name> |
Rename the current session |
/rm <path> |
Delete a session |
/config |
Show the current configuration |
/help, /quit |
— |
Requires Node 22.6+ for type stripping, and nothing else.
Security
The agent can run arbitrary shell commands as the user who started dox. That is the point, and it is why the server binds 127.0.0.1 and has no authentication of its own: anything that can reach the port already has your shell. Put authentication in front of it — see Deploy.