Skip to content

orhanrauf/pgfiles

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Postgres Files 🐘🗂️

Virtual filesystem backed by a single Postgres table.

Give your agent sandbox a working directory that persists in Postgres. The agent reads and writes files. It doesn't know a database exists underneath.

export PGFILES_DSN=postgres://db/app
export PGFILES_PREFIX=agents/agent-7f3a/
pgfiles mount .

echo '{"result": 42}' > output.json   # that's a Postgres INSERT
cat output.json                        # that's a SELECT

Install

brew install pgfiles

5-Second Start

# Set connection once — everything else reads from it
export PGFILES_DSN=postgres://db/app

# Bootstrap the schema (once)
pgfiles init

# Each agent gets its own prefix
AGENT_ID=$(uuidgen)
PGFILES_PREFIX="agents/$AGENT_ID/" pgfiles mount .

# The agent just sees a normal directory
mkdir output
echo '{"status": "done"}' > output/result.json
cat output/result.json

# Tear down — files live on in Postgres
pgfiles unmount .

Everything in . is a file or directory synced to Postgres. Every edit creates a new version.


How It Works

The table

One table. Four columns. That's the entire filesystem.

CREATE TABLE pgfiles (
    id    UUID    PRIMARY KEY DEFAULT gen_random_uuid(),
    key   TEXT    NOT NULL,
    meta  JSONB   NOT NULL DEFAULT '{}',
    data  BYTEA
);
Column What it does
id Immutable identity per version
key Object key — project/readme.md — flat, /-delimited
meta Version, timestamps, etag, content-type, your custom tags
data File body. NULL for directory markers.

Keys are flat

There are no real directories. project/readme.md is a key string. The / is a convention, not a hierarchy. When you ls, pgfiles does a prefix scan with delimiter grouping — the same way S3 works.

Versions are automatic

Every write creates a new row. The latest non-deleted version is "the file." Delete is a tombstone. Restore is always possible.


CLI Reference

pgfiles init [dsn]                     Create schema (reads PGFILES_DSN if omitted)
pgfiles mount [dsn] <path>             Mount filesystem (path can be ".")
pgfiles unmount <path>                 Unmount and flush

pgfiles where                          Show mount, prefix, cwd, key
pgfiles status                         Mount info, cache stats

pgfiles version <path>                 List versions
pgfiles restore <path> <version>       Promote old version
pgfiles purge <path>                   Hard-delete all versions
pgfiles purge-prefix <prefix>          Hard-delete a subtree

pgfiles batch                          Atomic multi-op from stdin

pgfiles cache clear                    Evict cache
pgfiles cache stats                    Hit rate, size

pgfiles config show                    Print resolved config

Configuration

The connection can be set three ways, in priority order:

# 1. CLI argument (highest priority)
pgfiles mount postgres://localhost/mydb .

# 2. Environment variable (recommended for sandboxes)
export PGFILES_DSN=postgres://localhost/mydb
pgfiles mount .

# 3. Config file (convenient for laptops)
# ~/.config/pgfiles/config.yaml

Environment variables

Variable Default Notes
PGFILES_DSN Connection string. The only required setting.
PGFILES_POOL_SIZE 10 Postgres connection pool size
PGFILES_PREFIX "" Key prefix for scoping
PGFILES_READ_ONLY false Reject all writes
PGFILES_CACHE_MAX_SIZE 1GB Local data cache cap
PGFILES_CACHE_METADATA_TTL 30s How long metadata is trusted
PGFILES_LOG_LEVEL warn debug, info, warn, error

Platform Support

OS Backend Notes
Linux FUSE3 fuser crate, talks to /dev/fuse directly
macOS NFS v4.1 Embedded NFS server on localhost, no kernel extension

Auto-detected. Single binary.


License

MIT

About

Virtual file system on Postgres.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors