Built-in Tools #
Ein ships with six tool plugins that give the agent the ability to execute shell commands, work with files, search file contents, and fetch pages from the web. Each tool call appears inline in the conversation pane as it runs.
How tool calls appear #
▸ Bash ls -la src/
total 40
drwxr-xr-x 8 you staff 256 May 6 11:30 .
drwxr-xr-x 15 you staff 480 May 6 11:00 ..
-rw-r--r-- 1 you staff 4096 May 6 10:45 main.rs
The ▸ ToolName indicator (steel blue) shows the tool name and its primary
argument. Bash streams up to five lines beneath it and keeps them after the call
finishes because its output is useful to the reader. Other tool results still
reach the model without being drawn in full.
Filesystem tools are limited to the connection's workspace roots. Tool plugins can reach only the hosts permitted by the server's tool policy. See Security & Sandboxing.
Bash #
Executes a shell command and returns its output.
▸ Bash cargo test --lib
running 12 tests
test config::tests::build_config_openrouter_default_base_url ... ok
...
test result: ok. 12 passed; 0 failed
Streaming: Bash output is streamed live as the command runs, so you see progress in real time without waiting for completion.
Empty output: if the command produces no output, the display shows (no output).
The command parameter is passed as a shell string and executed via the host
spawn syscall. Standard shell features (pipes, redirects, globbing) work as
expected. Bash is not yet confined to the WASM filesystem sandbox; see the
security guide before running an untrusted session.
Read #
Reads a file from the filesystem and returns its contents.
▸ Read src/main.rs
The file content is sent to the model but is not displayed in full in the conversation pane (it would be too verbose). The tool call indicator shows the file path.
The file must be within one of the connection's workspace roots.
Grep #
Searches file contents by regular expression and returns the matching lines with their paths and line numbers.
▸ Grep render_allowed_hosts
eind/src/grpc.rs:1797:fn render_allowed_hosts(hosts: &[String]) -> String {
eind/src/grpc.rs:1701: sections.push(render_allowed_hosts(&cfg.allowed_hosts));
Reach for this before Read when you're looking for something rather than reading something — which file defines a name, everywhere a function is called, whether a string appears at all. Point path at the narrowest place the answer could be; searching a whole repository for a common word returns a capped page of matches from everywhere. It's also the better choice over Bash with grep/rg/find: no shell quoting to get wrong, and results come back capped and numbered.
.git, .jj, target, and node_modules are never searched, and binary or
very large files are skipped. The searched path must be within one of the
connection's workspace roots.
Write #
Writes content to a file, creating it if it doesn't exist or overwriting it if it does.
▸ Write src/new_module.rs
The file path is shown in the indicator. The agent provides the full file contents; the write is atomic.
The target path must be within one of the connection's workspace roots.
Edit #
Replaces an exact string in a file with new content. More precise than Write for targeted changes.
▸ Edit src/config.rs
@@ -42,7 +42,7 @@
- let config_path = dirs::home_dir()
- .ok_or_else(|| anyhow::anyhow!("Cannot determine home directory"))?
+ let config_path = dirs::home_dir()
+ .ok_or_else(|| anyhow::anyhow!("Home directory not found"))?
The Edit tool renders a syntax-highlighted diff using the base16-ocean.dark theme. Up to 5 removed lines (red) and 5 added lines (green) are shown. For larger diffs the display is truncated but the full edit is applied.
The tool fails if the old_string is not found exactly in the file, or if it matches more than once. The agent handles retries.
WebFetch #
Fetches a URL over HTTP or HTTPS and returns its content: HTML is converted to readable markdown, plain text/JSON/XML come back verbatim, and anything else is refused by name rather than returned as raw bytes.
▸ WebFetch https://docs.rs/tokio/latest/tokio/task/
The tool follows redirects itself and upgrades a plain http:// URL to https:// automatically. There is no session and no script execution: a page behind a login or a paywall, or one that JavaScript builds after the page loads, comes back as whatever this one request actually received, not what a browser would render.
Fetched text is marked as untrusted data in the result — it's content written by whoever controls that page, not instructions, and should be read that way regardless of what it says.
WebFetch can only reach hosts the eind operator has allowed under
tool_policy.plugins.ein_webfetch.allowed_hosts. A client cannot widen that
list. See Network access.
Skill #
Loads the instructions for one of your skills. Unlike the tool plugins above this one is built into the server rather than a WASM plugin, and it only appears when ~/.ein/skills holds at least one skill.
▸ Skill commit-style
The indicator shows the skill name. See Skills for how to write one.