Plugins / Core

elelem-builtins

Read, write, run.

The default tools and slash commands: read and write files, run shell commands, and manage the session. Loaded automatically by the elelem command when installed.

gem install elelem-builtins

elelem-builtins turns a bare elelem install into a working agent. It adds 3 tools (read, write, execute), 7 slash commands, and the terminal output you see in elelem chat. execute gives the model a shell, so anything you can do from bash, it can do.

Install #

gem install elelem elelem-builtins

There is nothing to enable. The elelem executable requires elelem/builtins on startup if the gem is installed.

Configure #

ELELEM_CMD_TIMEOUT sets a limit, in seconds, for each execute command. When it expires, elelem sends TERM to the command’s process group, then KILL half a second later, and appends [command timed out after Ns] to the output. Without it, commands run until they exit.

Two optional programs improve the output when they are on your PATH:

  • bat shows files after read and write.
  • glow renders the model’s Markdown replies.

Without them, elelem prints plain text.

Use #

Tools #

ToolWhat it doesParams
readReturns the contents of a file. Aliases: open.path (required)
writeWrites a file, creating parent directories. Replaces the whole file.path, content (both required)
executeRuns bash -c COMMAND in the current directory and returns the exit status and combined stdout and stderr. Aliases: bash, sh, exec.command (required)

Details that matter:

  • read on a missing path returns the error not found.
  • Before write replaces an existing file, it prints a colored diff -u of the change, when stdin is a terminal. There is no prompt; the write happens either way.
  • After write, if a tool named verify exists (it does when elelem-tools is loaded), elelem runs it on the written path. You see its output; the model does not get its result.
  • execute streams output to the terminal as it arrives. Output longer than 10,000 characters is cut to the first and last 5,000, with a note saying how many characters were removed. A non-zero exit status is still a successful tool call; the model reads exit_status to tell.

The aliases write<|channel|> and execute<|channel|> also exist. They catch tool names some models emit with a stray chat-template token.

Slash commands #

CommandWhat it does
/helpLists the slash commands.
/exitExits elelem.
/clearClears the conversation history.
/contextLists each message in the context with its role and the first 60 characters.
/context NShows message N in full.
/context jsonPrints the full context, system prompt included, as JSON.
/providerLists registered providers.
/provider NAMESwitches to provider NAME for the rest of the session. The conversation is kept; --model is not passed to the new provider.
/reloadRe-runs the plugin files in ~/.agents/plugins and .agents/plugins. See limitations.
/toolsPrints a table of the available tools.
/tools NAMEPrints one tool’s description, parameters, and aliases.

/provider and /tools tab-complete their argument.

Example session #

elelem v0.13.0
> /tools
| Tool | Description |
|------|-------------|
| read | Read file |
| write | Write file |
| execute | Run shell command (supports pipes and redirections) |

How it works #

Each tool and command is a separate setup block in its own file under lib/elelem/builtins/, registered with Elelem.configure when the gem is required. The gem also registers Elelem::Builtins::Terminal as the output for interactive sessions. It prints a dot every 0.1 seconds while waiting for the model, renders Markdown through glow, marks failed execute calls with x, and copies everything it prints to a transcript file.

Transcripts are written to $XDG_STATE_HOME/elelem/sessions/TIMESTAMP-PID.transcript, which is ~/.local/state/elelem/sessions/ by default. They are plain append-only text, including terminal color codes. elelem does not read them back.

elelem ask does not use this output; it uses the core output, so no transcript is written for one-shot queries.

Limitations #

  • No permission checks. execute runs whatever the model sends, and write overwrites without asking. For prompts before a tool runs, add elelem-tools, which includes a permissions hook.
  • write always replaces the whole file. For targeted edits, the edit tool is in elelem-tools.
  • /reload clears every setup block before re-running plugin files. These setup blocks are registered once, when the gem is required, so after /reload the builtin tools and commands are gone, /reload included. Restart elelem instead.
  • Transcripts are never cleaned up.
  • /clear empties the conversation but not the system prompt, which is rebuilt from AGENTS.md on every request anyway.

Development #

git clone https://git.mokhan.ca/elelem/builtins.git
cd builtins
bin/setup
bin/test
bin/lint

The specs cover the Markdown rendering behind /tools.

Environment #

VariableDefaultDescription
ELELEM_CMD_TIMEOUTnoneSeconds before an execute command is killed. Unset or empty means no timeout.
XDG_STATE_HOME~/.local/stateBase directory for session transcripts, written to elelem/sessions/ under it.