eir is the command-line interface for the Entity Identifier Resolver (EIR).
The CLI provides tools for creating, building, inspecting, searching, modifying, merging, and maintaining EIR databases.
EIR is a local, strongly typed entity search and resolution engine. Entities can contain:
- aliases
- tags
- attributes
- sources
- relationships
The CLI is built on top of eir-core. The CLI does not implement the search engine itself; it exposes the database and search functionality provided by the core library.
Warning: EIR databases are not encrypted. Do not use EIR to store sensitive data unless the surrounding storage environment provides appropriate protection.
The current workspace is split into:
EntityIdentifierResolver/
├── crates/
│ ├── eir-core/
│ ├── eir-cli/
│ └── eir-version/
├── apps/
├── docs/
└── fixtures/
The main responsibilities are:
| Component | Responsibility |
|---|---|
eir-core |
Database, storage, indexing, query planning, search and entity types |
eir-cli |
Command-line interface |
eir-version |
Database/version/merge-related APIs |
fixtures |
Test and example entity datasets |
The workspace is defined in the root Cargo.toml.
During development, run the CLI through Cargo:
cargo run -p eir-cli -- <COMMAND>If the repository's Cargo alias is available:
cargo eir <COMMAND>Once installed, the command is simply:
eir <COMMAND>Show general help:
cargo eir --helpShow command-specific help:
cargo eir <COMMAND> --helpThe current CLI provides the following operations:
init
build
stats
inspect
search
insert
remove
update
compact
merge
server
completions
The CLI entry point dispatches these commands into the corresponding command implementations.
Some commands are intended primarily for local development and database maintenance.
An EIR database is no longer just a standalone serialized file.
The .eir file is the logical database identity. Physical storage lives alongside it.
A typical database looks like:
nutrition/
├── nutrition.eir
├── eir.toml
├── segments/
│ ├── 0000.deir
│ └── 0001.deir
└── wal/
The layout is managed by DatabasePaths and StorageConfig.
| Path | Purpose |
|---|---|
<name>.eir |
Logical database identity |
eir.toml |
Database/storage configuration |
segments/ |
Persistent DEIR storage segments |
wal/ |
Write-ahead log |
The database root is derived from the location of the .eir file when an existing database is opened.
Create an empty EIR database with:
cargo eir init data nutritionThis creates:
data/
└── nutrition/
├── nutrition.eir
├── eir.toml
├── segments/
└── wal/
The command accepts:
eir init <PARENT> <NAME>
For example:
cargo eir init data foodsThe init command delegates database creation to eir_core::engine::Engine::create.
Build a database from an entity dataset:
cargo eir build `
--input fixtures/entities.json `
--database data/entitiesThe command accepts:
eir build --input <INPUT> --database <DATABASE>
The build pipeline:
- Loads the entity input.
- Maps input entities into EIR's internal representation.
- Builds registries for tags, sources, attribute keys and relationship types.
- Builds the search indexes.
- Creates the
Database. - Writes the resulting database to storage.
The resulting database contains:
Database
├── Entities
├── Tag Registry
├── Source Registry
├── Attribute-Key Registry
├── Relationship-Type Registry
└── Indexes
EIR works with entity input documents.
A minimal entity can look like:
{
"id": 9100,
"aliases": ["Test Berry"],
"tags": ["test"],
"sources": [
{
"provider": "Test Source",
"verified": false
}
],
"attributes": [],
"relationships": []
}Entities are identified by their EntityID.
Entity data is converted into an internal EntityDocument when inserted into the database.
Registries convert repeated strings such as tags, source names, attribute keys and relationship types into compact internal IDs.
Show database statistics:
cargo eir stats data/entities/entities.eirThe command reports:
Database Statistics
===================
Entities: 46
Tags: 43
Sources: 2
Attributes: 15
Relationship Types: 5
Indexes
-------
Aliases: 89
Trie: 89
Fuzzy Aliases: 92
Tokens: 74
Tags: 43
Sources: 2
Relationships: 39
The exact numbers depend on the database.
Statistics are obtained from the in-memory Database representation and its indexes.
Inspect one or more entities:
cargo eir inspect data/entities/entities.eir 9100Multiple IDs can be supplied:
cargo eir inspect data/entities/entities.eir 1000 1001 1002The command accepts:
eir inspect <DATABASE> <ENTITY>...
Use verbose mode to display internal registry IDs:
cargo eir inspect data/entities/entities.eir 9100 --verboseExample:
Entity: 9100
Names:
Test Berry
Tags:
test
Attributes:
Relationships:
Sources:
Test Source
Verbose output can additionally show internal IDs for tags, attributes, relationships and sources.
If an entity is missing, the command reports:
Entity 9100 not found
Inspection reads the entity directly from the database maintained by Engine.
Search a database:
cargo eir search data/entities/entities.eir "FizzBerry"The optional result limit defaults to 10:
cargo eir search data/entities/entities.eir "FizzBerry" --limit 20The command accepts:
eir search <DATABASE> <QUERY> [--limit <N>]
Search results include:
- entity alias
- score
- search signals
- explanations
Example:
Search: FizzBerry
FizzBerry Spark score=1.00
Signals:
ExactAlias
PrefixAlias
Token
Why:
ExactAlias { ... }
FizzBerry Energy Blast score=0.78
Signals:
PrefixAlias
Token
Why:
PrefixAlias { ... }
The CLI obtains results through Engine::search(), which delegates to the resolver/search implementation in eir-core.
Search is separated into several stages.
At a high level:
Query
│
▼
Parser
│
▼
Intent / Filters
│
▼
Planner
│
▼
Search Executor
│
├── Exact Alias
├── Prefix Alias
├── Fuzzy Alias
├── Token
├── Tag
├── Attribute
└── Relationship
│
▼
Candidates
│
▼
Ranker
│
▼
Results
The query layer contains parsing, intent and filtering components. The search layer contains planning, execution, candidates, signals, ranking and results.
This means the CLI is intentionally thin:
eir-cli
│
▼
Engine
│
├── Database
│
└── Resolver
│
└── Search pipeline
EIR maintains specialized indexes for different search operations.
The current database index set includes:
| Index | Purpose |
|---|---|
| Alias index | Exact alias lookup |
| Trie | Prefix alias lookup |
| BK-tree | Fuzzy alias lookup |
| Inverted index | Token lookup |
| Tag posting lists | Tag → entities |
| Source posting lists | Source → entities |
| Attribute indexes | Attribute lookup |
| Relationship indexes | Relationship-based lookup |
The index structures are represented by Indexes and built by IndexBuilder.
Insert entities into an existing database:
cargo eir insert data/entities/entities.eir fixtures/test-entity.jsonThe input file may contain one or more entities.
The CLI:
- Opens the existing database.
- Loads the entities.
- Inserts each entity through
Engine. - Flushes the database.
An entity with an existing ID is rejected.
For example:
EntityAlreadyExists
The database itself also rebuilds its indexes after an insertion so the resolver reflects the new entity immediately.
Replace an existing entity:
cargo eir update `
data/entities/entities.eir `
9100 `
--input fixtures/test-entity-updated.jsonThe update input must contain exactly one entity.
The entity ID in the input must match the ID supplied to the command.
For example:
eir update <DATABASE> <ENTITY> --input <JSON>
The command validates:
- exactly one input entity
- matching entity IDs
before applying the update. It then flushes the updated database.
Remove one or more entities:
cargo eir remove data/entities/entities.eir 9100Multiple IDs can be supplied:
cargo eir remove data/entities/entities.eir 9100 9101 9102The command accepts:
eir remove <DATABASE> <ENTITY>...
Each entity is removed through Engine::remove().
After removal, the database rebuilds its search indexes so the removed entity is no longer searchable.
Database mutations are written through the storage backend.
The current engine uses a write-ahead log (WAL) for mutations.
Conceptually:
Insert / Remove
│
▼
WAL
│
▼
Database
│
▼
Resolver
When a database is opened, EIR:
- Resolves the physical database layout.
- Loads the persisted database snapshot.
- Replays pending WAL operations.
- Reconstructs the resolver.
This allows unflushed mutations to be recovered after reopening the database.
Engine::flush() writes the current database snapshot to persistent storage.
The CLI mutation commands use this mechanism after their operation completes.
For example:
insert
│
├── append WAL operation
├── update in-memory database
├── rebuild resolver
└── flush
The WAL is truncated after a successful flush.
Compaction rewrites persistent storage to reclaim space from obsolete data.
Run:
cargo eir compact data/entities/entities.eirOutput:
Database Compacted
==================
Before: 23.5 KB
After: 18.7 KB
Reclaimed: 4.8 KB
Savings: 20.4%
The actual values depend on the database.
Compaction operates on the physical database storage, including its segments.
It does not change the logical entity contents.
The command reports:
- storage size before compaction
- storage size after compaction
- reclaimed space
- percentage savings
The underlying Engine::compact() operation rewrites storage from the current database record.
Merge two EIR databases into a new output database:
cargo eir merge `
data/left/left.eir `
data/right/right.eir `
data/merged/merged.eirThe command accepts:
eir merge <LEFT> <RIGHT> <OUTPUT>
The merge operation:
- Loads both databases.
- Validates entity IDs.
- Combines the entity collections.
- Remaps registry IDs where necessary.
- Rebuilds indexes.
- Writes the merged database.
Duplicate entity IDs are rejected rather than silently overwritten.
The merge operation is designed to be atomic: validation occurs before the destination database is modified.
The CLI reports:
Merge complete.
Entities added: 42
Entities skipped: 0
The CLI contains the server command structure:
cargo eir server start data/entities/entities.eirThe server command accepts:
eir server start <DATABASE> [--host <HOST>] [--port <PORT>]
Defaults:
host = 127.0.0.1
port = 8765
The CLI also exposes:
cargo eir server closeThe server command is currently part of the CLI surface, but server functionality should be considered separate from the core local database/search architecture.
Generate shell completion scripts with:
cargo eir completions powershellSupported shells are:
bash
zsh
fish
powershell
elvish
The CLI uses clap_complete to generate completions from the command definition.
A typical workflow for creating and testing a database is:
cargo eir init data nutritioncargo eir build `
--input fixtures/entities.json `
--database data/nutritioncargo eir inspect `
data/nutrition/nutrition.eir `
1000cargo eir stats data/nutrition/nutrition.eircargo eir search `
data/nutrition/nutrition.eir `
"FizzBerry"cargo eir insert `
data/nutrition/nutrition.eir `
fixtures/test-entity.jsoncargo eir update `
data/nutrition/nutrition.eir `
9100 `
--input fixtures/test-entity-updated.jsoncargo eir remove `
data/nutrition/nutrition.eir `
9100cargo eir compact `
data/nutrition/nutrition.eirThe current EIR architecture is intentionally divided into layers.
eir-cli
│
▼
Engine
│
┌─────────┴─────────┐
▼ ▼
Database Resolver
│ │
┌─────┼─────┐ ┌─────┴─────┐
│ │ │ │ │
Entities Registries Indexes Search
│
┌──────┼──────┐
▼ ▼ ▼
Query Planner Ranker
Provides the command-line interface.
Provides the high-level database lifecycle API:
- create
- open
- search
- inspect
- insert
- remove
- update
- flush
- compact
The engine owns the storage backend, database and resolver.
Stores:
Entities
Registries
Indexes
The registries include:
- tags
- sources
- attribute keys
- relationship types
The database can rebuild indexes from the entity collection.
The storage subsystem contains:
Backend
DEIR segments
Segment manager
Store
WAL
Registries
Posting lists
Indexes
These components provide the persistent storage layer beneath the logical database.
The query layer is responsible for turning user input into structured search intent and filters.
Query
├── Parser
├── Intent
├── Filters
└── Types
The search layer executes the planned operations and ranks candidates.
Search
├── Planner
├── Executor
├── Operators
├── Candidate
├── Signal
├── Ranker
├── Context
└── Result
The current lifecycle is:
Entity Dataset
│
▼
Build
│
▼
Logical Database
│
┌────────┼────────┐
│ │ │
Search Inspect Stats
│
┌─────┼─────────────┐
│ │ │
Insert Update Remove
│ │ │
└─────┼─────────────┘
│
▼
WAL
│
▼
Snapshot
│
▼
Compaction
The important distinction is that logical database state and physical storage are separate concerns.
The .eir path identifies the database, while the storage backend manages snapshots, segments and WAL data.
EIR currently favors deterministic index rebuilding over maintaining complex incremental index mutations.
When an entity is inserted or removed:
Database entities
│
▼
IndexBuilder
│
▼
All search indexes
This ensures the resolver is reconstructed from the current entity collection.
The indexes therefore remain consistent with the database documents after mutations.
The core library contains tests for the database, persistence, storage and search layers.
Run the core tests:
cargo test -p eir-coreRun the CLI tests:
cargo test -p eir-cliRun the complete workspace:
cargo test --workspaceImportant areas covered by the current test suite include:
- database creation
- database opening
- persistence
- WAL recovery
- insertion
- removal
- compaction
- merging
- duplicate entity detection
- index rebuilding
- exact alias search
- prefix search
- fuzzy search
- token search
- tags
- attributes
- relationships
- query planning
- ranking
EIR is still under active development.
The current repository describes the CLI, storage and search layers as functional, while the server remains incomplete.
In particular:
- The server interface exists, but the server implementation is not yet complete.
- Search output is currently intended for human-readable CLI use.
- Database mutations rebuild search indexes.
- The CLI does not yet expose every internal storage/index operation.
- The database format is still evolving.
Applications depending on EIR should therefore expect database and API formats to evolve until a stable format/versioning policy is established.
The EIR CLI is a management and development interface over the EIR engine.
Its primary responsibilities are:
Create
↓
Build
↓
Inspect / Stats / Search
↓
Insert / Update / Remove
↓
Flush / Recover
↓
Compact
↓
Merge
The CLI itself is intentionally thin. The important functionality lives in eir-core:
eir-cli
│
▼
Engine
│
├── Database
│ ├── Entities
│ ├── Registries
│ └── Indexes
│
├── Storage
│ ├── Segments
│ └── WAL
│
└── Resolver
│
├── Query
├── Planner
├── Executor
└── Ranker
This architecture allows the same database and search engine to be used by the CLI, future server interfaces, and applications embedding EIR directly.