Tools

KHAELOR gives the model exactly seven powerful primitives — not dozens of micro-tools. Every tool call is permission-checked before it runs, rendered as a compact one-liner in the conversation, and journaled in the session's event log.

ToolWhat it doesYou see
readRead a file (paged, line-numbered)▸ Read src/kernel/agent.ts · lines 1–2000 of 3417
writeCreate or fully replace a file▸ Write src/context/budget.ts · new file · 114 lines
editSurgical in-place replacement▸ Edit src/context/engine.ts · +31 −12
grepContent search (ripgrep)▸ Search "ContextEngine" · 14 matches in 5 files
globFind files by name pattern▸ Glob src/**/*.ts · 23 files
bashRun a short-lived shell command▸ Run npm test · exit 0 · 3.2s
processManage background processes▸ Process start npm run dev · p3 running

There is deliberately no git tool — git flows through bash under the same permission rules, where you can see and gate every command.

read#

Reads files with line numbers, up to 2,000 lines per page; the output always states the total and how to continue, so the agent pages through large files instead of dumping them. Guard rails you benefit from:

  • Binary detection — binary files are described (type, size), never dumped as bytes.
  • Size guard — files over 10 MB are refused with guidance to search or page instead.
  • Near-miss suggestions — a typo'd path gets "Did you mean…?" candidates from the repository index.
  • Directories — reading a directory lists its entries instead of erroring.

Every successful read is also recorded in the session's file registry — this is what powers the safety rule that the agent must read before it writes (below).

write#

Writes a complete file, creating parent directories as needed. Two protections guard your work on existing files:

  • Read-before-write — the agent cannot overwrite a file it has not read in this session. It is structurally impossible for it to blow away content it never saw.
  • External-modification detection — if the file changed on disk after the agent last read it (you edited it, or another process did), the write is refused and the agent must re-read and reapply. Your concurrent edits are never clobbered.

Writes are atomic (temp file + fsync + rename), preserve line endings (CRLF), BOM, and file mode bits. Every write produces a unified diff you can expand instantly with d or review in /diff.

edit#

The most important tool: exact string replacement inside a file. The agent supplies the text to find and its replacement; KHAELOR requires the match to be unambiguous. Under the hood, a nine-strategy matching cascade makes edits robust without making them reckless:

  1. Exact match
  2. Line-trimmed match (whitespace drift at line edges)
  3. Whitespace-normalized match
  4. Indentation-flexible match (block quoted at the wrong indent depth — the file's real indentation is preserved)
  5. Escape-normalized match (over-escaped \n, \t, quotes)
  6. Trimmed-boundary match
  7. Block-anchor fuzzy match (first/last lines as anchors, similarity-scored middle)
  8. Context-aware fuzzy match (last resort)
  9. Multi-occurrence replace-all (exact matches only — fuzzy mass-replace is never allowed)

The guards matter as much as the strategies: an ambiguous match (multiple locations) fails with the line numbers instead of silently picking one; a fuzzy match that would replace a disproportionately large region is refused. Failed edits return precise repair guidance to the model — the closest near-miss with the exact line and character difference — so the agent fixes itself instead of thrashing. Same read-before-edit and external-modification protection as write; same instant diff.

grep#

Fast regex content search over the repository, powered by ripgrep (bundled — no system dependency). Results are grouped by file with line numbers, ordered by most recently modified, and hard-capped at 100 matching lines so the model's context never drowns in output. Respects .gitignore and .khaelorignore. When results are truncated, the full result set is spilled to a file the agent can search further.

glob#

Filesystem discovery by name pattern — **/*.ts, src/**/config.* — returning up to 100 paths ordered newest-first. Respects ignore files and skips built-in noise (node_modules/, .git/, dist/) unless the pattern explicitly targets it.

bash#

Runs short-lived shell commands — builds, tests, git, package scripts — and returns interleaved stdout/stderr with the exit code and duration:

 $ npm test
 > proj@0.3.1 test
 > vitest run
   src/context/engine.test.ts (14 tests)
 [exit code 0 · 3.2s · cwd /Users/x/dev/proj]
  • Commands run in their own process group, non-interactively, from the project directory (or an explicit working directory) — never via hidden cd side effects.
  • A failing exit code is a normal observation for the agent, not a crash — it reads the failure and fixes the cause.
  • Permission evaluation happens on the parsed command before execution — see Permissions.

The timeout that never kills your command

This is KHAELOR's answer to the classic agent failure of hanging forever on a dev server. If a bash command is still running when its time budget expires (default 120 s, max 300 s), it is not killed — it is adopted by the background process manager, keeps running with its output continuously logged, and the agent immediately gets the output so far plus a process id:

 Command still running after 120s — moved to background as process p4.
 Output so far:
 ...
 Use process read p4 for new output, or process stop p4 to stop it.

Nothing blocks forever; nothing is silently killed. (Pressing Esc yourself does kill a foreground bash command — you asked for that — while background processes survive.)

process#

A real background process manager the agent can drive: start, list, read, write (stdin), stop. It is what lets KHAELOR start a dev server, keep editing, check the server's output, run tests, and check the server again — the workflow blocking-shell agents simply cannot do.

 Started p3 (pid 41232): npm run dev
 cwd /Users/x/dev/proj · log ~/.khaelor/process-logs/s_ab12/p3.log
 First output (waited up to 2s):
   VITE v5.4.1  ready in 431 ms
   ➞  Local: http://localhost:5173/
  • Instant-failure detectionstart waits up to 2 s for first output, so port-in-use and similar immediate crashes are caught inline without blocking healthy servers.
  • Nothing is lost — each process keeps an in-memory ring buffer and a complete log file on disk (~/.khaelor/process-logs/<session>/<id>.log). Reads return "new output since last read"; older output stays readable by offset or from the log.
  • Interactive processeswrite sends stdin (REPLs, prompts), then automatically reads the response.
  • Clean stopsstop terminates the whole process group (SIGTERM, 3 s grace, SIGKILL), so grandchild processes don't linger.
  • Lifecycle — processes survive Esc interruptions but end with the session (with notice). Exits are detected and shown even if nobody is reading.

You can watch and control everything yourself in /processes; the status bar shows a live count of running processes.

Output truncation and spill files#

Every tool that can produce large output truncates it middle-out — head and tail kept, one explicit marker in between — and spills the complete output to disk:

 [... 1,842 lines omitted (58 KB). Full output:
  ~/.khaelor/tool-output/s_ab12/bash-toolu_9.txt — read or grep that file for the rest.]

The agent gets the spill path and can read or grep it; you see a · truncated badge on the tool row and can expand from the same file. Spill files are session-scoped, garbage-collected with the session, and capped at 512 MB globally (oldest sessions pruned first). A 40,000-line test log can never destroy your conversation layout — what settles into the transcript is bounded.

Inspecting tool calls#

  • Live: Ctrl+T toggles a rolling 12-line tail of the currently-running tool.
  • After: d prints the most recent edit's diff; /diff opens the full session diff viewer; each turn's tool calls can be expanded into full detail blocks on demand.
  • Always: every tool call — inputs, results, approval decisions — is a durable event in the session event log.