{
  "markdown": "<div align=\"center\">\n  <img src=\"assets/logo.png\" alt=\"Basalt logo\" width=\"128\">\n  <h1>Basalt</h1>\n  <p>A CLI-first local SQL workspace for structured data and coding agents.</p>\n  <p>\n    <a href=\"https://github.com/joshiii-xyz/basalt/actions/workflows/ci.yml\">\n      <img src=\"https://github.com/joshiii-xyz/basalt/actions/workflows/ci.yml/badge.svg\" alt=\"CI\">\n    </a>\n    <a href=\"LICENSE\">\n      <img src=\"https://img.shields.io/badge/license-MIT-blue.svg\" alt=\"MIT license\">\n    </a>\n  </p>\n</div>\n\nBasalt is an embedded SQL database and command-line application built from\nscratch in Rust. It provides a small library API, an interactive shell,\ndurable storage, snapshot-isolated transactions, crash recovery, portable\nstructured-data workspaces, and a stdio MCP server for local AI agents. It is\nnot a SQLite-compatible replacement or a hosted database.\n\n## Highlights\n\n- SQL lexer and recursive-descent parser with expressions, joins, grouping,\n  aggregates, aliases, and transaction statements.\n- Atomic statement execution with primary-key, UNIQUE, and user-created\n  indexes.\n- Snapshot-isolated transactions with optimistic conflict detection.\n- Checksummed page snapshots and a write-ahead log that recovers committed\n  state after a process crash.\n- Simple query planning with table scans, equality indexes, and range indexes.\n- Interactive and scriptable CLI output in table, CSV, and JSON-lines formats.\n- Portable workspaces with versioned metadata and atomic CSV, JSON/JSONL, and\n  SQL dump import/export.\n- Installable MCP server with typed SQL tools, bounded workspace imports and\n  exports, engine-bounded SQL, schema resources, and recoverable agent changes.\n\n## Installation\n\nRust 1.88 or newer is required for a Cargo install.\n\n```bash\ncargo install basalt-db --locked\n```\n\nThe published package is named `basalt-db`; the installed command remains\n`basalt`. To install the current checkout instead, use\n`cargo install --path . --locked`.\n\nTagged releases include checksummed installers and prebuilt binaries for Linux,\nmacOS, and Windows. See [GitHub Releases](https://github.com/joshiii-xyz/basalt/releases)\nfor the current no-toolchain install. The latest tagged release is verified\nfrom its published installer and its checksums:\n\n```bash\ncurl --proto '=https' --tlsv1.2 -LsSf https://github.com/joshiii-xyz/basalt/releases/latest/download/basalt-db-installer.sh | sh\n```\n\nTo run directly from a checkout:\n\n```bash\ncargo run --release -- app.basalt\n```\n\n## Quick start\n\nOpen a database and run SQL interactively:\n\n```console\n$ basalt app.basalt\nbasalt> CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL);\nbasalt> INSERT INTO users VALUES (1, 'Ada');\nbasalt> SELECT * FROM users;\nid | name\n---+-----\n1  | Ada\n1 row(s)\n```\n\nFor a one-shot command:\n\n```bash\nbasalt --json --command \"SELECT * FROM users ORDER BY id;\" app.basalt\n```\n\nUse `Database::in_memory()` for an ephemeral database. Durable writes are\nappended to the WAL immediately; call `checkpoint()` to fold the current state\ninto the snapshot and clear old WAL frames. A durable path is owned by one\nprocess at a time; cloned `Database` handles share that owner safely across\nthreads, while a second process receives an \"already open\" error.\n\n## Workspaces\n\nUse a workspace when an agent or script needs a disposable, local relational\narea for CSV, JSON, logs, issue exports, or fixtures:\n\n```bash\nbasalt init .basalt-workspace\nbasalt workspace import --table issues .basalt-workspace issues.csv\nbasalt workspace inspect --json .basalt-workspace\nbasalt workspace query --json .basalt-workspace \"SELECT * FROM issues ORDER BY id\"\nbasalt workspace export .basalt-workspace issues issues.jsonl\n```\n\nImports are atomic, recoverable, and return a durable `change_id`; exports are\ndeterministic. Add `--json` to workspace import/export commands when an agent or\nscript needs a machine-readable operation report; raw exports to `-` remain\nclean data streams. Later writes can be previewed, applied by exact plan ID,\ninspected in history, diffed with schema and row-change counts, and undone when\nthey are the latest change. A workspace is owned by one Basalt process while\nopen, so stop a\nworkspace MCP server before using that workspace from the CLI or by opening its\n`data.basalt` file directly. See [docs/workspaces.md](docs/workspaces.md) for\nthe format and boundaries.\n\nThe reason to use Basalt for agent-owned data is the write boundary: inspect a\nproposed change before it is durable, apply only the exact reviewed plan, then\ndiff or undo the latest change if needed.\n\n```bash\nbasalt workspace preview --json .basalt-workspace \\\n  \"UPDATE issues SET status = 'closed' WHERE id = 42\"\n# Review the returned plan_id, then:\nbasalt workspace apply --json .basalt-workspace PLAN_ID\n# Review the returned change_id, then:\nbasalt workspace diff --json .basalt-workspace CHANGE_ID\nbasalt workspace undo --json .basalt-workspace CHANGE_ID\n```\n\nUse SQLite or DuckDB when you need their compatibility or analytical\nperformance. Basalt is for local structured-data work where a bounded,\nrecoverable write matters more than replacing an existing database.\n\nIf that describes your workflow, use the [early-user validation\nguide](docs/early-user-validation.md) with a disposable, non-sensitive input\nand record the concrete task and blocker. Basalt does not claim adoption until\ndevelopers complete this workflow against the tools they already use.\n\n## MCP server\n\nBasalt can run as a local [Model Context Protocol](https://modelcontextprotocol.io/)\nserver over stdio. Install the binary from this checkout:\n\n```bash\ncargo install --path . --locked\n```\n\nThen configure an MCP host with an absolute workspace path. Workspace mode is\nthe recommended agent integration: it scopes data access and requires an\nexplicit preview/apply lifecycle for writes.\n\n```json\n{\n  \"mcpServers\": {\n    \"basalt\": {\n      \"command\": \"basalt\",\n      \"args\": [\n        \"mcp\",\n        \"--workspace\",\n        \"/absolute/path/to/project-data\",\n        \"--init-workspace\"\n      ]\n    }\n  }\n}\n```\n\n`--init-workspace` creates the configured workspace only when its path does not\nexist; it never replaces an existing directory or manifest. Omit it when the\nworkspace must be provisioned separately. Add `\"--allow-writes\"` only when the\nhost has an explicit operator approval policy for applying workspace plans and\nundoing changes. Direct database mode is still available with `\"args\": [\"mcp\",\n\"/absolute/path/to/app.basalt\"]`, but it is read-only by default; `execute` and\n`checkpoint` require the same flag. Use `\"args\": [\"mcp\", \":memory:\"]` for an\nephemeral direct-mode session. The installed binary is preferred for host\nconfiguration; running from a checkout is also possible with `cargo run --quiet\n-- mcp --workspace /absolute/path/to/project-data`.\n\nWhen a modern MCP host advertises form elicitation, Basalt returns an\n`input_required` approval request before each workspace import, apply, or undo\nand executes only after the host retries with an explicit approval. Legacy\ninitialized hosts receive `elicitation/create`; hosts that do not advertise\nelicitation use the explicit `--allow-writes` startup policy.\n\nThe release metadata carries the visible Cargo ownership marker used by the\nMCP Registry listing:\n\n- MCP Registry ownership marker: mcp-name: io.github.joshiii-xyz/basalt\n- Published listing: [io.github.joshiii-xyz/basalt](https://registry.modelcontextprotocol.io/v0.1/servers?search=io.github.joshiii-xyz%2Fbasalt)\n\nWorkspace mode exposes `workspace_import`, `workspace_inspect`,\n`workspace_preview`, `workspace_plan`, `workspace_apply`,\n`workspace_history`, `workspace_diff`, `workspace_undo`, and\n`workspace_export`, alongside bounded `query`, `list_tables`, and\n`describe_table` tools. It also exposes the current schema at\n`basalt://schema`. See [docs/mcp.md](docs/mcp.md) for the complete tool\ncontract, configuration details, approval boundary, and troubleshooting.\n\n## CLI\n\nExecute a SQL file:\n\n```bash\nbasalt --file schema-and-seed.sql app.basalt\n```\n\nRun commands in order on one connection, including a transaction spanning\nmultiple commands:\n\n```bash\nbasalt --command \"BEGIN;\" --command \"INSERT INTO users VALUES (2, 'Grace');\" --command \"COMMIT;\" app.basalt\n```\n\nUse `--file -` to read SQL from stdin. Repeat `--command` and `--file` as\nneeded; they execute in the order they appear. Table output is human-readable,\nCSV emits query rows, and `--json` emits one JSON object per statement. Run\n`.help` inside the shell for `.tables`, `.schema`, `.mode`, `.headers`,\n`.checkpoint`, `.show`, and `.clear`. Each CLI SQL action and the pending\ninteractive buffer is limited to 16 MiB; larger scripts should be split into\nsmaller actions or use the bounded workspace import formats.\n\n## Library usage\n\n```rust\nuse basalt::{Database, db::StatementResult};\n\nlet database = Database::open(\"example.basalt\")?;\ndatabase.execute_sql(\n    \"CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL); INSERT INTO users VALUES (1, 'Ada');\",\n)?;\nlet result = database.execute_sql(\"SELECT * FROM users WHERE id = 1\")?;\nassert!(matches!(result[0], StatementResult::Select { .. }));\ndatabase.checkpoint()?;\n# Ok::<(), basalt::db::DbError>(())\n```\n\nUse `database.connect()` when SQL transaction statements need to span multiple\ncalls.\n\n## Project layout\n\n| Path | Purpose |\n| --- | --- |\n| src/sql/ | Lexer, parser, AST, and SQL dialect |\n| src/engine.rs | Statement execution and query semantics |\n| src/planner.rs | Access-path selection |\n| src/db.rs, src/database.rs | Tables, constraints, transactions, and API |\n| src/storage.rs, src/wal.rs | Snapshots, checksums, and recovery |\n| src/cli.rs | Interactive and scripted command-line frontend |\n| src/workspace.rs | Local workspace lifecycle and data interchange |\n| src/mcp.rs | Stdio MCP server, agent tools, and schema resource |\n| server.json | MCP Registry release metadata |\n| docs/sql.md | Supported SQL dialect and transaction semantics |\n| docs/benchmark-results.md | Recorded workflow benchmark snapshot |\n| docs/compatibility.md | File-format boundary and differential-test policy |\n| docs/production-readiness.md | Technical release contract, limits, and evidence |\n| docs/early-user-validation.md | Five-minute switching test and feedback template |\n| docs/fuzzing.md | Parser and persistence fuzzing instructions |\n| docs/mcp.md | MCP installation, configuration, and tool contract |\n| docs/workspaces.md | Workspace layout and import/export contract |\n| tests/ | Integration and crash-recovery coverage |\n| benches/ | In-process engine throughput benchmark |\n| scripts/benchmark_workspace.py | Reproducible workflow comparison harness |\n| scripts/differential_sql.py | Supported-subset SQLite differential checks |\n| scripts/mcp-smoke.py | Installed-binary writable MCP smoke test |\n| scripts/verify-release-artifacts.py | Release archive checksum and contents check |\n| scripts/verify-registry-metadata.py | MCP Registry package/version consistency check |\n| scripts/release-check.sh | Packaged-crate and release preflight |\n| scripts/smoke-test.sh | Installed-binary CLI and read-only MCP smoke test |\n| fuzz/ | Optional libFuzzer parser and snapshot targets |\n\n## Development\n\n```bash\ncargo fmt --all -- --check\ncargo check --all-targets --locked\ncargo clippy --all-targets --all-features --locked -- -D warnings\ncargo test --all-targets --locked\nRUSTDOCFLAGS=\"-D warnings\" cargo doc --no-deps --locked\ncargo bench --bench throughput\ncargo package --locked\ncargo build --release --locked\ncargo audit\npython3 scripts/benchmark_workspace.py --basalt target/release/basalt\n```\n\nFor the complete Unix release preflight, use:\n\n```bash\nbash scripts/release-check.sh\n```\n\nIt installs the exact packaged crate into a temporary prefix and runs the\ninstalled-binary smoke journey. It also runs `cargo audit` and `dist plan`\nwhen those tools are available.\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for contribution guidelines and\n[CHANGELOG.md](CHANGELOG.md) for project history. The release checklist is in\n[docs/release.md](docs/release.md), including the generated release workflow\nand clean-binary smoke test.\n\n## License\n\nMIT. See [LICENSE](LICENSE).\n",
  "bytes": 12188,
  "sha": "6a14426aa3a4440806175c6133bd1732f351f2795b5f89f4caee1da602018700",
  "repo_slug": "joshiii-xyz/basalt",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_joshiii_xyz_basalt_aace376f/readme"
}