بنقرة واحدة
tigerfs
// How to discover, read, write, and search data in a TigerFS-mounted PostgreSQL database using file tools.
// How to discover, read, write, and search data in a TigerFS-mounted PostgreSQL database using file tools.
| name | tigerfs |
| description | How to discover, read, write, and search data in a TigerFS-mounted PostgreSQL database using file tools. |
TigerFS mounts PostgreSQL databases as directories. You interact with data using Read, Write, Glob, and Grep -- no SQL needed. File-first mode gives you a transactional, shareable filesystem backed by a database. Data-first mode lets you explore and manipulate an existing database using file tools. Most work uses file-first.
Each directory in a TigerFS mount is either file-first or data-first:
.md or .txt files. Read and write files normally. See files.md..info/ directory. Access rows as files or directories. See data.md.mount/
├── notes/ # File-first (markdown workspace)
│ ├── hello.md
│ ├── tutorials/ # Subdirectories: ls shows only real files; .history/<file>/ remains path-accessible
│ ├── .history/ # Versioned history (root level only)
│ ├── .log/ # Operation log (root level only; pipeline hidden from ls)
│ ├── .savepoint/ # Named bookmarks for undo (root level only)
│ └── .undo/ # Preview and apply undo operations (root level only)
├── snippets/ # File-first (plain text workspace)
│ └── bash-loop.txt
├── .tables/ # Backing tables in tigerfs schema
│ └── notes/ # Data-first access to notes backing table
├── users/ # Data-first (standalone table)
│ ├── .info/
│ ├── .by/
│ └── 1/ 2/ 3/ ...
├── .info/ # Mount-level metadata (user identity)
└── .build/ # Create new workspaces
A transactional, shareable filesystem backed by a database. Multiple users and agents can read and write concurrently. Create workspaces with .build/:
Bash "echo 'markdown' > mount/.build/notes"
Bash "echo 'markdown,history' > mount/.build/notes" # with versioned history
Bash "echo 'plaintext' > mount/.build/snippets" # body-only, no frontmatter
See files.md for full details on schemas, column roles, directories, and history.
Because the filesystem is transactional and shared, it can implement collaborative workflows. Follow the recipe exactly:
| If asked to... | Follow |
|---|---|
| Create a task list, kanban, todo, or project tracker | recipes.md Recipe 4. Core rule: directories = states (todo/, doing/, done/); mv = transitions; do NOT use status frontmatter. |
| Create a knowledge base, wiki, or documentation store | recipes.md Recipe 5 |
| Save or resume session context | recipes.md Recipe 6 |
| Keep a log of what you do | recipes.md Recipe 7 |
| Revert, roll back, or undo changes | See Safe Editing below and files.md |
Before making multiple or risky edits, always create a savepoint:
Bash "echo '{\"description\":\"Before investigating bug #42\"}' > mount/workspace/.savepoint/before-investigation.json"
When to create a savepoint: investigating a bug, debugging, refactoring, multi-file edits, or any uncertain operation.
When to undo: user asks to revert, agent realizes the approach isn't working, or changes were made to wrong files.
Before undoing: always preview first and get user confirmation. Undo is destructive.
Undo is undoable: undo operations are logged (type='undo'), so you can undo an undo. Create a savepoint before a major undo for extra safety -- if the result isn't what was expected, undo back to that savepoint.
"Create a savepoint"
Bash "echo '{\"description\":\"<why>\"}' > mount/workspace/.savepoint/<name>.json"
"What changed since the savepoint?"
Read "mount/workspace/.undo/to-savepoint/<name>/.info/summary"Bash "cd mount/workspace && diff -ru .undo/to-savepoint/<name> . -x '.*'""What changed in this file?"
Read "mount/workspace/<dir>/.history/<file>/.id" (for a root-level file: Read "mount/workspace/.history/<file>/.id")Read "mount/workspace/.log/.by/file_id/<uuid>/.last/5/.export/json""Show me the diff"
Bash "cd mount/workspace && diff -ru .undo/to-savepoint/<name> . -x '.*'"Bash "diff -u --color mount/workspace/.log/<id>/before mount/workspace/.log/<id>/after""Undo to the savepoint"
Read "mount/workspace/.undo/to-savepoint/<name>/.info/summary"Bash "touch mount/workspace/.undo/to-savepoint/<name>/.apply""Undo this one change"
file_id, adjacent timestamps), each must be undone — see How agent writes appear in the log.Read "mount/workspace/.undo/id/<log_id>/.info/summary"Bash "diff -u --color mount/workspace/.log/<id>/before mount/workspace/.log/<id>/after"Bash "touch mount/workspace/.undo/id/<log_id>/.apply". For a multi-entry group, apply each entry's undo (newest log_id first) (or touch .undo/to-id/<id-before-the-group>/.apply to reverse the whole group atomically).Different write methods produce different numbers of log entries:
Write/Edit, many editors): the operation produces multiple adjacent log entries. Typically: a create of a temp file like <file>.tmp.<pid>.<hash>, then for an overwrite a delete of the existing target, then a rename of the temp to the final name. That's 2 entries for a new file, 3 for an overwrite. The create and rename share the temp file's file_id; the delete (when present) carries the original target's file_id.echo "..." > file, in-place editors): a single create (new file) or edit (existing file) log entry. No temp file, no rename.To revert a logical operation, find its group of entries, then undo them:
Read "mount/workspace/.log/.last/8/.export/json".rename to your target filename -- its file_id is the new file. The paired create shares that same file_id (filename <basename>.tmp.<pid>.<hash>); the delete (overwrites only) is the adjacent entry with the target filename but a different file_id. Checks: create+rename share a file_id; count is 2 (new file) or 3 (overwrite). filename is not a .by/-indexed column, so don't filter by it -- to get the id without scanning, read .history/<file>/.id, then query .log/.by/file_id/<id>/.touch .undo/id/<log_id>/.apply, newest first -- order is mandatory; each step sets up the next. Out of order is destructive: RPC struct is bad on the stale .tmp.*, or silent deletion of the live file.Shortcut: when the group is the latest change, touch .undo/to-id/<id-just-before-it>/.apply reverses it atomically in order. Never revert by re-typing content with Write/Edit -- that adds another rename group and loses the audit trail.
For advanced cases (filtered undo, per-user undo, pipeline queries), construct paths directly from files.md. See recipes.md Recipes 1-3 for complete workflow patterns.
Direct access to database rows as files and directories. Use when you need column-level access, index lookups, bulk export, or structured data processing.
Read "mount/users/.info/count" # Row count
Read "mount/users/1.json" # Row as JSON
Read "mount/users/1/email" # Single column
Glob "mount/users/.by/email/alice@example.com/*" # Index lookup
Read "mount/users/.by/status/active/.export/json" # Filtered export
| Size | Strategy |
|---|---|
| ~100 rows or less | Glob patterns and row-as-directory access are fine |
| 100 - 1,000 rows | Prefer .export/ over reading individual rows to avoid 1 query per row. Use .by/, .filter/, .first/, .last/, .sample/ for selective access when possible |
| 1,000+ rows | Large tables are limited to 1,000 rows by default; use .all/ if you actually need all rows. Strongly prefer .export/ over reading individual rows. Use .by/, .filter/, .first/, .last/, .sample/ for selective access whenever possible |
Always check .info/count first to choose the right strategy.
See data.md for the full reference.
| Goal | Tool Call |
|---|---|
| File-First | |
| List files | Glob "mount/workspace/*.md" or Glob "mount/workspace/**/*.md" (recursive) |
| Read file | Read "mount/workspace/file.md" |
| Write file | Write "mount/workspace/file.md" with content |
| Delete file | Bash "rm mount/workspace/file.md" |
| Search | Grep pattern="term" path="mount/workspace/" |
| History versions | Glob "mount/workspace/.history/file.md/*" |
| Read old version | Read "mount/workspace/.history/file.md/<timestamp>" |
| Savepoints & Undo | |
| Create savepoint | Bash "echo '{\"description\":\"Before refactoring\"}' > mount/workspace/.savepoint/name.json" |
| Diff all changes since savepoint | Bash "cd mount/workspace && diff -ru .undo/to-savepoint/name . -x '.*'" |
| File drift since a change | Bash "diff -u --color mount/workspace/.log/<id>/before mount/workspace/.log/<id>/current" |
| View recent log | Read "mount/workspace/.log/.last/10/.export/json" |
| Data-First | |
| Row count | Read "mount/t/.info/count" |
| Schema / columns | Read "mount/t/.info/schema" or .info/columns |
| Read row | Read "mount/t/pk.json" or Read "mount/t/pk/column" |
| Read multiple rows (small) | Glob "mount/t/*.json" then read individually |
| Read multiple rows (medium/large) | Read "mount/t/.export/tsv" (also .export/json, .csv, .yaml) |
| Navigate rows | Glob "mount/t/.first/N/*", .last/N/*, or .sample/N/* |
| Index lookup | Glob "mount/t/.by/col/val/*" |
| Filtered export | Read "mount/t/.by/col/val/.export/json" |
| Update | Write "mount/t/pk/col" or Write "mount/t/pk.json" (PATCH) |
| Insert row | Write "mount/t/new.json" with JSON |
| Delete row | Bash "rm mount/t/pk" |
Virtual directory layout: .history/, .log/, .savepoint/, .undo/ only appear in ls at the workspace root level, not inside subdirectories. Subdirectories' ls shows only real files; .history/<file>/ and .history/<file>/.id remain path-accessible from subdirectories.
Pipeline capabilities (.by/, .filter/, .order/, .export/, etc.) behave differently depending on where they appear:
.log/ or .savepoint/: accessible by explicit path but hidden from ls (prevents recursive scanner blowup on exponential pipeline branching).ErrInvalidPath and a hint pointing at mount/.tables/<workspace>/ — that's the entry point for data-first access to a workspace's backing table.mount/users/) or under mount/.tables/<workspace>/: fully accessible.Never recursively scan these directories -- always use targeted access patterns from the Quick Reference above:
.log/ -- pipeline capabilities hidden from listing, use .log/.last/10/.export/json.savepoint/ -- same as .log/, use explicit paths.history/ -- one entry per file version; grows with every edit.undo/ -- preview trees that mirror the affected file hierarchy.by/<column>/ -- lists every distinct value; each expands to filtered rows.filter/<column>/ -- same as .by/ with higher limit.export/ -- reading files triggers full table/query dumps.import/ -- write interface; scanning could trigger unintended operationsSafe to scan:
Glob "mount/workspace/**/*.md").info/ -- small, fixed set of metadata files| Don't | Do Instead |
|---|---|
| File-First | |
Put status: in frontmatter to track state | Use directories as states (todo/, doing/, done/), mv to transition |
Use Write or Edit to restore prior file content -- even for a single file. The tool's write-temp-then-rename pattern creates 2-3 new log entries instead of reverting the originals. | Use TigerFS's undo machinery: .undo/to-savepoint/<name>/.apply for groups of changes, .undo/id/<log_id>/.apply for one operation. See How agent writes appear in the log for grouping multi-entry writes. |
| Undo without previewing first | Always read .info/summary and get user confirmation before applying |
| Data-First | |
| Read individual rows in a loop for large tables | Use .export/json or .export/csv for bulk access |
| Write full row JSON expecting replace semantics | JSON/CSV/TSV writes are PATCH -- only specified keys update |
Grep across all rows of a large table | Use .by/ index lookups for indexed columns |
| Glob a data-first directory without checking size | Read .info/count first, choose strategy based on table size |
When asked to create, mount, fork, or manage a database or filesystem, see ops.md for tigerfs CLI commands.