
inGitDB is a developer-grade, schema-validated, AI-native database whose storage engine
is a
Git
repository. Every record is a plain YAML or JSON file, every change is a commit, and every team
workflow β branching, code review, pull requests β extends naturally to data. This makes inGitDB
simultaneously a database, a version-control system, an event bus, and a data layer for AI agents,
all with zero server infrastructure for reads.
π‘ Why inGitDB?
- Plain files, real Git. Records are YAML or JSON files you can read in any editor, diff in any
pull request, and clone with a single
git clone. No binary blobs, no proprietary format.
- Full Git history for free. Branching, merging, bisect, and revert work on your data exactly
as they do on your code β because the data is in your code repository.
- Schema validation built in. Collections are defined with typed column schemas in YAML. The
ingitdb validate command checks every record and reports violations with the collection,
file path, and field name.
- Zero server infrastructure for reads. There is no daemon to run. Reading data is a
file-system operation on a git clone.
- AI-native via MCP. The planned MCP server (
ingitdb serve --mcp) will expose CRUD operations
to AI agents through the Model Context Protocol β no custom integration required (Phase 6).
- Go library via DALgo.
pkg/dalgo2ingitdb implements the DALgo
dal.DB interface, so any Go program can use inGitDB as a standard database abstraction.
βοΈ How it works
flowchart LR
A([YAML / JSON\nrecord files]) --> B[(Git repository\non disk)]
B --> C[ingitdb validate\nschema + data check]
C --> D[Views Builder\ngenerates $views/]
D --> E([CLI output\ningitdb query])
D --> F([Go programs\nDALgo API])
D --> G([AI agents\nMCP server β Phase 6])
The ingitdb validate command reads .ingitdb.yaml, checks every record against its collection
schema, and rebuilds materialized views in the same pass. Validation can be scoped to a commit
range (--from-commit / --to-commit) so CI stays fast on large databases.
β¬οΈ Installation
macOS β Homebrew
brew tap ingitdb/cli
brew install ingitdb
Linux
AUR (Arch Linux)
yay -S ingitdb-bin
Snap
snap install ingitdb
Linuxbrew
brew tap ingitdb/cli
brew install ingitdb
Windows
WinGet
winget install ingitdb
Chocolatey
choco install ingitdb
Scoop
scoop bucket add ingitdb https://github.com/ingitdb/scoop-bucket
scoop install ingitdb
go install github.com/ingitdb/ingitdb-cli/cmd/ingitdb@latest
Binary download
Pre-built binaries for all platforms are available on the GitHub Releases page.
π Quick start
# Build the CLI
go build -o ingitdb ./cmd/ingitdb
# Validate a database directory (schema + records)
ingitdb validate
# Validate a specific path
ingitdb validate --path=/path/to/your/db
# Validate only collection definitions
ingitdb validate --only=definition
# Validate only records (skip schema validation)
ingitdb validate --only=records
# Validate only records changed between two commits (fast CI mode)
ingitdb validate --from-commit=abc1234 --to-commit=def5678
# List all collections
ingitdb list collections
# List collections nested under a path (regular expression)
ingitdb list collections --in='countries/(ie|gb)'
# List collections whose name contains "city"
ingitdb list collections --filter-name='*city*'
# Search records for a substring across all fields
ingitdb find --substr=Dublin
# Search records using a regular expression, limited to 10 results
ingitdb find --re='pop.*[0-9]{6,}' --limit=10
# Search only specific fields
ingitdb find --substr=Dublin --fields=name,capital
# Scope a search to a sub-path
ingitdb find --exact=Ireland --in='countries/.*' --fields=country
# Delete all records from a collection (keeps the schema)
ingitdb truncate --collection=countries.counties
# Delete a specific collection and all its records
ingitdb delete collection --collection=countries.counties.dublin
# Delete records matching a pattern within a collection
ingitdb delete records --collection=countries.counties --filter-name='*old*'
# --- Record CRUD (requires record_file.type: "map[string]any" collections) ---
# Create a new record: the --id format is <collection-id>/<record-key>
# (collection IDs allow alphanumeric and "." only; "/" separates collection and key)
ingitdb create record --path=. --id=geo.nations/ie --data='{title: "Ireland"}'
# Read a record (output format: yaml or json)
ingitdb read record --path=. --id=geo.nations/ie
ingitdb read record --path=. --id=geo.nations/ie --format=json
# Update fields of an existing record (patch semantics: only listed fields change)
ingitdb update record --path=. --id=geo.nations/ie --set='{title: "Ireland, Republic of"}'
# Delete a single record
ingitdb delete record --path=. --id=geo.nations/ie
π Accessing GitHub Repositories Directly
inGitDB can read and write records in a remote GitHub repository without cloning it. The
--github flag replaces --path and points the CLI at a GitHub repository over the REST API.
π Public repositories (no token required)
# Read a record
ingitdb read record --github=owner/repo --id=countries/ie
# Pin to a specific branch, tag, or commit SHA
ingitdb read record --github=owner/repo@main --id=todo.tags/active
ingitdb read record --github=owner/[email protected] --id=todo.tags/active
# List all collections
ingitdb list collections --github=owner/repo
π Private repositories
Supply a token via the GITHUB_TOKEN environment variable or the --token flag. All write
operations also require a token, even for public repositories.
# Set the token once in your shell
export GITHUB_TOKEN=ghp_...
ingitdb read record --github=owner/repo --id=countries/ie
ingitdb list collections --github=owner/repo
ingitdb create record --github=owner/repo --id=countries/ie --data='{name: Ireland}'
ingitdb update record --github=owner/repo --id=countries/ie --set='{name: Ireland, capital: Dublin}'
ingitdb delete record --github=owner/repo --id=countries/ie
# Or pass the token inline (not recommended for scripts β it ends up in shell history)
ingitdb read record --github=owner/repo --token=ghp_... --id=countries/ie
Each write operation (create record, update record, delete record) creates a single commit
in the remote repository. No local clone is required at any point.
See GitHub Direct Access for the full reference,
including authentication details, rate limit notes, and limitations.
A minimal .ingitdb.yaml at the root of your DB git repository:
rootCollections:
tasks.backlog: data/tasks/backlog
tasks.inprogress: data/tasks/in-progress
languages:
- required: en
| Command |
Status |
Description |
version |
β
done |
Print build version, commit hash, and date |
validate |
β
done |
Check every record against its collection schema |
read record |
β
done |
Read a single record by ID (local or GitHub) |
create record |
β
done |
Create a new record in a collection |
update record |
β
done |
Update fields of an existing record (local or GitHub) |
delete record |
β
done |
Delete a single record by ID (local or GitHub) |
list collections |
β
done |
List collection IDs (local or GitHub) |
list view |
π‘ planned |
List view definition |
list subscribers |
π‘ planned |
List subscribers |
find |
π‘ planned |
Search records by substring, regex, or exact value |
delete collection |
π‘ planned |
Remove a collection |
delete view |
π‘ planned |
Remove view definition |
delete records |
π‘ planned |
Remove records from a collection |
truncate |
π‘ planned |
Remove all records from a collection, keeping its schema |
query |
π‘ planned |
Query and format records from a collection |
materialize |
π‘ planned |
Build materialized views into $views/ |
pull |
π‘ planned |
Pull remote changes and rebuild views |
watch |
π‘ planned |
Stream record change events to stdout |
serve |
π‘ planned |
Start MCP, HTTP API, or file-watcher server |
resolve |
π‘ planned |
Interactive TUI for resolving data-file merge conflicts |
setup |
π‘ planned |
Initialise a new database directory |
migrate |
π‘ planned |
Migrate records between schema versions |
rebase |
β
done |
Rebase on top of a base ref and resolve README conflicts |
The --id flag uses / to separate collection ID from the record key:
<collection-id>/<record-key>
Collection IDs may contain only alphanumeric characters and . (e.g. geo.nations), and must start
and end with an alphanumeric character. Use / only after the collection ID (e.g. --id=geo.nations/ie).
The longest matching collection prefix wins when ambiguous.
Only collections with record_file.type: "map[string]any" support CRUD. Collections using
[]map[string]any (list) or map[string]map[string]any (dictionary) are not yet implemented.
See the CLI reference for flags and examples.
π Documentation
| Document |
Description |
| Documentation |
Full docs index β start here |
| CLI reference |
Every subcommand, flag, and exit code |
| Features |
What inGitDB can do today and what is coming |
| GitHub Direct Access |
Read and write records in remote GitHub repositories without cloning |
| Architecture |
Data model, package map, and key design decisions |
| Roadmap |
Nine delivery phases from Validator to GraphQL |
| Contributing |
How to open issues and submit pull requests |
| Competitors |
Honest feature comparison with related tools |
π€ Get involved
inGitDB is small enough that every contribution makes a visible difference. The best way to start
is to point the CLI at a directory of YAML files and run ingitdb validate, then check the
Roadmap to see what is being built next.
To contribute:
- Read CONTRIBUTING.md for the pull-request workflow.
- Browse open issues to find something to work on.
- Open or comment on an issue before investing time in a large change.
Bug reports, documentation improvements, and questions are all welcome.
π¦ Dependencies
- DALgo β Database Abstraction Layer for Go
π License
This project is free, open source and licensed under the MIT License. See the LICENSE
file for details.