RAGFS: a filesystem interface for agents, and the query JSON I keep as a retrieval receipt

Community Article
Published October 10, 2026

This is an adapted repost. The canonical originals are two articles on my site: Why I Gave Agents a Filesystem Instead of Another API and A Retrieval Receipt Is the JSON the Query Wrote. If the two versions ever differ, the site wins.

An agent working in a directory can already list, read and write paths. Giving it a separate API for file management creates a second interface for the same material. I wanted an operation's result, and the way to undo it, to be available through the filesystem too.

RAGFS (open source) is my Linux FUSE implementation of that idea. It mounts an indexed directory and exposes a virtual .ragfs control directory. The underlying files stay in the source directory. Documentation: gianlucamazza.github.io/ragfs.

One operation, from request to undo

The README quick start keeps the mount in the foreground:

mkdir ~/ragfs-mount
ragfs mount ~/Documents ~/ragfs-mount --foreground

To remove docs/old.md, the agent writes the relative path to the delete control file and reads the JSON result:

echo "docs/old.md" > ~/ragfs-mount/.ragfs/.ops/.delete
cat ~/ragfs-mount/.ragfs/.ops/.result

The delete moves the file to trash, and the result contains an undo_id. The agent can keep that identifier and write it to the safety control file to reverse the operation:

echo "<undo_id>" > ~/ragfs-mount/.ragfs/.safety/.undo

The sequence is what matters: request, inspect the result, keep the undo id, undo if needed. This is an interface contract, not evidence that an agent will always make the right deletion decision. I still review what an agent intends to remove.

Search on the same mount

The same mount can search the directory. RAGFS extracts text, splits it into chunks, embeds them locally with thenlper/gte-small through Candle, and stores the vectors in LanceDB. The model downloads on first use. Later embedding queries use the local model and do not call an external embedding API. The index stays outside the source tree.

It is a practical index, with limits that the README states:

  • Code chunking finds function and class signatures by pattern matching, not a tree-sitter AST.
  • Cosine search is an exact scan until an IVF-PQ index is built, at 256 chunks or more. L2 and dot-product search stay exact.
  • FUSE runs on Linux only.

The receipt is the query JSON

A retrieval step I cannot re-read later is a story, not a record. The User Guide documents what a query prints:

ragfs query ./src "error handling implementation" -f json
{
  "query": "error handling implementation",
  "results": [
    { "file": "src/lib.rs", "score": 0.847, "content": "Handle errors gracefully by...", "lines": "45:52" }
  ]
}

Five fields are what I keep as the retrieval receipt: query (the string I asked), file (the path of a hit), score (what the command printed for that hit), content (the snippet) and lines (the line range). JSON is the form I keep because a script can read it.

The 0.847 above is the User Guide's example value. It shows the field. It is not a measured run, and it is not a retrieval-quality benchmark.

What I do not claim

  • I have not published a retrieval-quality or scale benchmark for this setup, so I do not treat the implementation choices above as proof of better answers.
  • A receipt says what the command returned. It does not say the hit was the right passage. Relevance still needs an evaluation. When retrieval is weak, my order is to measure first, then inspect chunking and ranking before changing the embedding model (RAG in Production).
  • The README marks the CLI, the FUSE mount, agent operations under .ops/ and the safety layer under .safety/ as stable. Semantic organize, dedupe and cleanup are beta and propose a plan that needs approval before execution. The Python bindings and the MCP server are beta too. A file interface does not remove the need for that approval boundary.
  • I do not claim a client or a company uses RAGFS.

"Trust me, the context was relevant" is not a receipt. The query JSON is.

Links: repository · documentation · User Guide · embedding model thenlper/gte-small

Gianluca Mazza. I take LLM systems into production: state, recovery, eval, cost. gianlucamazza.it

Community

Sign up or log in to comment