Overview of TigerFS
mainls, cat, grep, and rm instead of writing SQL queries. This makes database data accessible to AI coding assistants (like Claude Code) and standard command-line tools that expect a filesystem interface.repository·main·Indexed 20 days ago
https://github.com/timescale/tigerfsTigerFS is a versioned filesystem backed by PostgreSQL that provides a filesystem interface to database tables. It allows humans and AI agents to interact with structured data using standard Unix tools via two modes: File-first for content management with automatic versioning and undo operations, and Data-first for exploring existing databases. It features pipeline queries via path segments, schema management through filesystem operations, and support for mounting cloud backends like Tiger Cloud and Ghost.
ls, cat, grep, and rm instead of writing SQL queries. This makes database data accessible to AI coding assistants (like Claude Code) and standard command-line tools that expect a filesystem interface.TigerFS is a transactional, concurrent filesystem designed for human-agent collaboration. It treats files as the primary API for interacting with databases.
Core Capabilities:
.history/<file>/.before/current/after diff symlinks to preview changes or roll back states.mkdir to create a table..modify/ draft to propose schema alterations.touch .commit to apply the changes.ls and cat to navigate complex queries. You can chain filters, sorting, pagination, and column projection into a single path that translates into an optimized SQL query.tigerfs migrate for in-place, idempotent updates to schemas, triggers, and indexes across releases. Supports --dry-run and --describe flags.The TigerFS implementation roadmap outlines the project's core capabilities, ranging from basic FUSE filesystem mounting to advanced synthesized applications. Key functional areas include:
.first/N/, .last/N/), random sampling (.sample/N/), and large table escape hatches (.all/)..history/, .log/, .savepoint/, and .undo/ interfaces to manage data changes and recovery.For tables with multi-column primary keys, TigerFS uses a comma-delimited path representation.
Path Format:
(customer_id, product_id) with values (5, 42), the directory name is 5,42.%2C to prevent path ambiguity.Example:
If a table order_items has a composite PK (customer_id, product_id):
ls /mount/order_items/ might show 1,100.cat /mount/order_items/1,100/quantity retrieves the value for that specific composite row.# Manual verification of composite PK
psql -c "CREATE TABLE order_items (customer_id int, product_id int, quantity int, PRIMARY KEY (customer_id, product_id));"
psql -c "INSERT INTO order_items VALUES (1, 100, 5), (1, 200, 3);"
ls /mount/order_items/ # Should show: 1,100
cat /mount/order_items/1,100 # Should show row dataTigerFS provides several special path patterns and virtual files to interact with database content using standard filesystem tools:
.all/: An escape hatch for interacting with large tables..first/N/ and .last/N/: Used for pagination to retrieve the first or last N records..sample/N/: Used for random sampling of N records..count: A virtual file representing the total row count..order/<column>/: Capability to navigate or query data ordered by a specific column..by/: Used for index-based navigation..columns, .schema, and .count: Metadata files describing the table structure and size..indexes: Metadata file describing available indexes..ddl: Extended schema file..info/: A subdirectory containing metadata about the table or view..export/: Bulk read capability..import/: Bulk write capability.In TigerFS, data stored in the memFile cache is committed to the underlying database based on the following triggers:
| Trigger | Description |
|---|---|
Sync() | Triggered by editor saves (e.g., fsync). Performs an immediate commit. |
Close() with refCount=0 | The last open handle to the file is closed. |
| Idle timeout (5 min) | A background reaper commits entries that have been idle for more than 5 minutes (handles crashed clients). |
| Server shutdown | A graceful shutdown flushes all dirty entries to the database. |
TigerFS uses a layered credential resolution strategy to find PostgreSQL database credentials. It prioritizes standard PostgreSQL conventions to ensure compatibility across desktop, server, container, and CI/CD environments.
When looking for a password, TigerFS checks sources in the following order of precedence (highest to lowest):
PGPASSWORD or TIGERFS_PASSWORD environment variables.password_command: An external command configured in the settings used to fetch secrets from a manager.~/.pgpass file: The standard PostgreSQL password file (handled via the pgx library).Note: TigerFS does not use system keyrings (like macOS Keychain or Windows Credential Manager) and does not support plain-text passwords in the configuration file.
To support arbitrary user-defined metadata in markdown files without changing the database schema, TigerFS uses a headers JSONB column.
How it works:
headers JSONB column are merged into the YAML frontmatter block (sorted alphabetically after known columns).title or author), TigerFS collects these "unknown" keys and stores them in the headers JSONB column.headers JSONB column in the database.Requirement: The underlying table must have a headers JSONB DEFAULT '{}'::jsonb column for this to function.
TigerFS maps PostgreSQL table privileges to standard Unix filesystem permissions. Permissions are checked lazily and cached in memory for the lifetime of the mount.
| PostgreSQL Privilege | Filesystem Permission | Description |
|---|---|---|
SELECT | r-- | Read permission |
UPDATE | -w- | Write permission on existing rows |
INSERT | -w- | Write permission on new rows |
DELETE | rm capability | Ability to remove files/directories |
Example:
SELECT + UPDATE on a users table will see files as -rw-r--r--.SELECT will see files as -r--r--r--.TigerFS supports cloud-native backends like Tiger Cloud and Ghost using a URI prefix scheme. Instead of passing traditional database flags, you can use prefixes to identify the backend service.
Supported Prefixes:
tiger:<id>ghost:<id>Cloud Commands:
create [BACKEND:]NAME [MOUNTPOINT]: Creates a new resource on the specified backend.fork SOURCE [DEST]: Forks an existing resource.info [MOUNTPOINT]: Displays detailed information about a cloud-backed mount.Mounting with a prefix:
Instead of using --host or --user, pass the prefixed connection string directly to the mount command.
Example:
go run ./cmd/tigerfs mount tiger:my-service-id /tmp/cloudmountTigerFS allows you to access tables from different PostgreSQL schemas using two methods:
Schema Prefixes: Use the schema name as a directory prefix in your path.
/users/ maps to public.users (default schema)./analytics/reports/ maps to analytics.reports.Explicit Access via .schemas/: Use the .schemas/ directory to browse all available schemas explicitly.
/.schemas/public/users/ maps to public.users.The default schema is configurable via the TigerFS configuration.
# Example: Accessing a table in the 'analytics' schema
ls /tmp/testmount/analytics/
# Example: Explicit access via .schemas directory
ls /tmp/testmount/.schemas/public/To prevent column names from colliding with reserved capability names (like .first or .last), all index-based navigation is moved under a .by/ subdirectory. This directory contains subdirectories for every indexed column (single or composite).
Example Structure:
.by/email/: Access via the email index..by/last_name.first_name/: Access via the composite last_name and first_name index.# Example directory structure
/mnt/db/users/
├── .by/
│ ├── email/ # single-column index
│ │ └── foo@example.com/
│ └── last_name.first_name/ # composite index
│ └── Smith/
│ └── John/
├── .info/
└── 1/