Basalt is an embedded SQL database and command-line application built from
scratch in Rust. It provides a small library API, an interactive shell,
durable storage, snapshot-isolated transactions, crash recovery, portable
structured-data workspaces, and a stdio MCP server for local AI agents. It is
not a SQLite-compatible replacement or a hosted database.
Highlights
Local SQL workspaces with bounded, recoverable writes for coding agents.
2026-11-09
Estrellas
—
Herramientas
—
Disponibilidad
—
SQL lexer and recursive-descent parser with expressions, joins, grouping,
aggregates, aliases, and transaction statements.
Atomic statement execution with primary-key, UNIQUE, and user-created
indexes.
Snapshot-isolated transactions with optimistic conflict detection.
Checksummed page snapshots and a write-ahead log that recovers committed
state after a process crash.
Simple query planning with table scans, equality indexes, and range indexes.
Interactive and scriptable CLI output in table, CSV, and JSON-lines formats.
Portable workspaces with versioned metadata and atomic CSV, JSON/JSONL, and
SQL dump import/export.
Installable MCP server with typed SQL tools, bounded workspace imports and
exports, engine-bounded SQL, schema resources, and recoverable agent changes.
Installation
Rust 1.88 or newer is required for a Cargo install.
cargo install basalt-db --locked
The published package is named basalt-db; the installed command remains
basalt. To install the current checkout instead, use
cargo install --path . --locked.
Tagged releases include checksummed installers and prebuilt binaries for Linux,
macOS, and Windows. See GitHub Releases
for the current no-toolchain install. The latest tagged release is verified
from its published installer and its checksums:
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/yoshiii-xyz/basalt/releases/latest/download/basalt-db-installer.sh | sh
To run directly from a checkout:
cargo run --release -- app.basalt
Quick start
Open a database and run SQL interactively:
$ basalt app.basalt
basalt> CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL);
basalt> INSERT INTO users VALUES (1, 'Ada');
basalt> SELECT * FROM users;
id | name
---+-----
1 | Ada
1 row(s)
For a one-shot command:
basalt --json --command "SELECT * FROM users ORDER BY id;" app.basalt
Use Database::in_memory() for an ephemeral database. Durable writes are
appended to the WAL immediately; call checkpoint() to fold the current state
into the snapshot and clear old WAL frames. A durable path is owned by one
process at a time; cloned Database handles share that owner safely across
threads, while a second process receives an "already open" error.
Workspaces
Use a workspace when an agent or script needs a disposable, local relational
area for CSV, JSON, logs, issue exports, or fixtures:
Imports are atomic, recoverable, and return a durable change_id; exports are
deterministic. Add --json to workspace import/export commands when an agent or
script needs a machine-readable operation report; raw exports to - remain
clean data streams. Later writes can be previewed, applied by exact plan ID,
inspected in history, diffed with schema and row-change counts, and undone when
they are the latest change. A workspace is owned by one Basalt process while
open, so stop a
workspace MCP server before using that workspace from the CLI or by opening its
data.basalt file directly. See docs/workspaces.md for
the format and boundaries.
The reason to use Basalt for agent-owned data is the write boundary: inspect a
proposed change before it is durable, apply only the exact reviewed plan, then
diff or undo the latest change if needed.
basalt workspace preview --json .basalt-workspace \
"UPDATE issues SET status = 'closed' WHERE id = 42"
# Review the returned plan_id, then:
basalt workspace apply --json .basalt-workspace PLAN_ID
# Review the returned change_id, then:
basalt workspace diff --json .basalt-workspace CHANGE_ID
basalt workspace undo --json .basalt-workspace CHANGE_ID
Use SQLite or DuckDB when you need their compatibility or analytical
performance. Basalt is for local structured-data work where a bounded,
recoverable write matters more than replacing an existing database.
If that describes your workflow, use the early-user validation
guide with a disposable, non-sensitive input
and record the concrete task and blocker. Basalt does not claim adoption until
developers complete this workflow against the tools they already use.
MCP server
Basalt can run as a local Model Context Protocol
server over stdio. Install the binary from this checkout:
cargo install --path . --locked
Then configure an MCP host with an absolute workspace path. Workspace mode is
the recommended agent integration: it scopes data access and requires an
explicit preview/apply lifecycle for writes.
--init-workspace creates the configured workspace only when its path does not
exist; it never replaces an existing directory or manifest. Omit it when the
workspace must be provisioned separately. Add "--allow-writes" only when the
host has an explicit operator approval policy for applying workspace plans and
undoing changes. Direct database mode is still available with "args": ["mcp", "/absolute/path/to/app.basalt"], but it is read-only by default; execute and
checkpoint require the same flag. Use "args": ["mcp", ":memory:"] for an
ephemeral direct-mode session. The installed binary is preferred for host
configuration; running from a checkout is also possible with cargo run --quiet -- mcp --workspace /absolute/path/to/project-data.
When a modern MCP host advertises form elicitation, Basalt returns an
input_required approval request before each workspace import, apply, or undo
and executes only after the host retries with an explicit approval. Legacy
initialized hosts receive elicitation/create; hosts that do not advertise
elicitation use the explicit --allow-writes startup policy.
The release metadata carries the visible Cargo ownership marker used by the
MCP Registry listing:
Workspace mode exposes workspace_import, workspace_inspect,
workspace_preview, workspace_plan, workspace_apply,
workspace_history, workspace_diff, workspace_undo, and
workspace_export, alongside bounded query, list_tables, and
describe_table tools. It also exposes the current schema at
basalt://schema. See docs/mcp.md for the complete tool
contract, configuration details, approval boundary, and troubleshooting.
CLI
Execute a SQL file:
basalt --file schema-and-seed.sql app.basalt
Run commands in order on one connection, including a transaction spanning
multiple commands:
Use --file - to read SQL from stdin. Repeat --command and --file as
needed; they execute in the order they appear. Table output is human-readable,
CSV emits query rows, and --json emits one JSON object per statement. Run
.help inside the shell for .tables, .schema, .mode, .headers,
.checkpoint, .show, and .clear. Each CLI SQL action and the pending
interactive buffer is limited to 16 MiB; larger scripts should be split into
smaller actions or use the bounded workspace import formats.
Library usage
use basalt::{Database, db::StatementResult};
let database = Database::open("example.basalt")?;
database.execute_sql(
"CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL); INSERT INTO users VALUES (1, 'Ada');",
)?;
let result = database.execute_sql("SELECT * FROM users WHERE id = 1")?;
assert!(matches!(result[0], StatementResult::Select { .. }));
database.checkpoint()?;
# Ok::<(), basalt::db::DbError>(())
Use database.connect() when SQL transaction statements need to span multiple
calls.
Project layout
Path
Purpose
src/sql/
Lexer, parser, AST, and SQL dialect
src/engine.rs
Statement execution and query semantics
src/planner.rs
Access-path selection
src/db.rs, src/database.rs
Tables, constraints, transactions, and API
src/storage.rs, src/wal.rs
Snapshots, checksums, and recovery
src/cli.rs
Interactive and scripted command-line frontend
src/workspace.rs
Local workspace lifecycle and data interchange
src/mcp.rs
Stdio MCP server, agent tools, and schema resource
server.json
MCP Registry release metadata
docs/sql.md
Supported SQL dialect and transaction semantics
docs/benchmark-results.md
Recorded workflow benchmark snapshot
docs/compatibility.md
File-format boundary and differential-test policy
docs/production-readiness.md
Technical release contract, limits, and evidence
docs/early-user-validation.md
Five-minute switching test and feedback template
docs/fuzzing.md
Parser and persistence fuzzing instructions
docs/mcp.md
MCP installation, configuration, and tool contract
It installs the exact packaged crate into a temporary prefix and runs the
installed-binary smoke journey. It also runs cargo audit and dist plan
when those tools are available.
See CONTRIBUTING.md for contribution guidelines and
CHANGELOG.md for project history. The release checklist is in
docs/release.md, including the generated release workflow
and clean-binary smoke test.
Aún no hay lista de herramientas. Los servidores remotos la reciben tras la primera comprobación de estado.
Preguntas frecuentes
Preguntas
¿Cómo instalo Basalt?
Copia en esta página la configuración stdio para Cursor, Claude Desktop, Claude Code o VS Code. Usa la instalación del publicador, no un proxy de PlugMCP.
¿Basalt necesita una clave de API?
Este registro no indica ninguna variable de entorno obligatoria.
¿Qué transporte usa Basalt?
Basalt se ejecuta localmente por stdio.
¿Cuándo se comprobó Basalt por última vez?
Última comprobación: 2026-11-09. Local SQL workspaces with bounded, recoverable writes for coding agents.