fold
fold.
one filesystem for everything your agent touches.
your agent doesn't care if the data lives in S3, a local SQLite file, a Slack channel, or a model running on your machine. it shouldn't have to.
fold gives every data source the same interface — so your agent uses cat, ls, grep, and pipes across all of them. no SDKs to juggle. no auth flows to manage per source. one tool.
npm install @tbc-fold/nodebuilding an agent that touches more than one data source means managing multiple SDKs, multiple auth setups, and multiple mental models — all before you've written a single line of actual agent logic.
and then you hand a 12-tool list to your LLM and hope it picks the right one.
fold is one tool. a bash interface backed by real data sources. LLMs already know bash cold. fold exploits that.
see how it works.
quick exampleimport { Workspace, LocalFSResource, SQLiteResource } from '@tbc-fold/node'
const ws = new Workspace({
'/notes': new LocalFSResource({ path: '~/Documents' }),
'/db': new SQLiteResource({ path: './app.db' }),
})
// list tables with row counts and schemas
await ws.execute('ls -c /db')
// search across notes
await ws.execute('grep -r "refund" /notes | head -n 10')
// copy a file between mounts
await ws.execute('cp /notes/report.md /db/reports/1')built differently.
differentiatorslocal-first
S3 and Slack are great. but not everything should leave your machine.
fold treats your local filesystem, SQLite databases, and locally running models (via Ollama) as first-class resources — not afterthoughts. build agents that work entirely on-device with zero data egress and zero API keys required.
reactive, not just pull
most agent tools wait to be called. fold can call your agent.
ws.watch() lets any resource push events when data changes — a new file, a Slack message, a database write. your agent triggers automatically. no polling. no cron jobs.
LLMs already know bash
instead of teaching your model a new API schema per data source, fold gives it one interface it was trained on millions of times: bash.
cat, ls, grep, wc, head, pipe. the model knows exactly what to do. ls -c adds rich metadata to listings — so the agent understands the environment in one tool call instead of five.
how it's structured.
architecture┌──────────────────────────────────────────────────────────┐
│ your agent │
│ ws.execute('grep error /slack/incident/') │
└─────────────────────────┬────────────────────────────────┘
│
┌─────────────────────────▼────────────────────────────────┐
│ Workspace │
│ ┌─────────────┐ ┌──────────────┐ ┌─────────────────┐ │
│ │ Executor │ │ Cache │ │ Reactive Engine │ │
│ │ (13 cmds) │ │ (RAM/Redis) │ │ (ws.watch) │ │
│ └─────────────┘ └──────────────┘ └─────────────────┘ │
├──────────────────────────────────────────────────────────┤
│ Mount Table │
│ /notes → LocalFSResource │
│ /db → SQLiteResource │
│ /s3 → S3Resource │
│ /slack → SlackResource │
│ /model → OllamaResource │
└──────────────────────────────────────────────────────────┘workspace sits between your agent and every backend.
the executor parses bash, the reactive engine handles push events,
the cache keeps network calls cheap.
resources implement five methods. that's the entire contract.
resources.
available resources| resource | package | what it maps | deps |
|---|---|---|---|
| RAMResource | @tbc-fold/node | in-memory filesystem | none |
| LocalFSResource | @tbc-fold/node | local disk with path protection | none |
| SQLiteResource | @tbc-fold/node | tables → dirs, rows → JSON files | better-sqlite3 |
| OllamaResource | @tbc-fold/node | local LLM inference as file reads | none |
| S3Resource | @tbc-fold/node | S3, R2, MinIO objects | @aws-sdk/client-s3 |
| SlackResource | @tbc-fold/node | channels → dirs, messages → JSONL | @slack/web-api |
| GitHubResource | @tbc-fold/node | repos and files via GitHub API | none |
| RedisResource | @tbc-fold/node | Redis keys as files | ioredis |
build your own in 5 methods. list, read, write, stat, delete. add subscribe() for reactive support. add listWithContext() for rich ls -c output.
built-in commands.
built-in commands| command | description |
|---|---|
| cat <path> | read file contents |
| ls <path> | list directory. -l long format, -c rich context with metadata |
| cp <src> <dst> | copy across any two resources |
| mv <src> <dst> | move across any two resources |
| rm <path> | delete file or directory |
| grep <pattern> <files> | search contents. -i case-insensitive, -n line numbers, -r recursive |
| wc | count lines (-l), words (-w), bytes (-c) |
| head -n N | first N lines |
| tail -n N | last N lines |
| find <path> -name <glob> | recursive file search |
| echo <text> | write text to stdout |
| mkdir <path> | create directory |
| jq <query> | basic JSON path query |
pipes (|), output redirects (>, >>), and quoted strings all work.
no shell subprocess. everything runs in-process.
works with claude, cursor, and any mcp client.
mcp integrationfold exposes any workspace as an MCP server out of the box. one file. your data is available everywhere MCP runs.
// mcp-server.ts
import { Workspace, LocalFSResource, SQLiteResource } from '@tbc-fold/node'
import { startMCPServer } from '@tbc-fold/mcp'
const ws = new Workspace({
'/notes': new LocalFSResource({ path: '~/Documents' }),
'/db': new SQLiteResource({ path: './data.db' }),
})
await startMCPServer(ws)// claude / cursor mcp config
{
"mcpServers": {
"fold": {
"command": "npx",
"args": ["tsx", "mcp-server.ts"]
}
}
}plug into your agent framework.
agent frameworks// langchain / langgraph
import { foldTools } from '@tbc-fold/agents'
const tools = foldTools(workspace)
// vercel ai sdk
import { foldTool } from '@tbc-fold/agents'
const tools = foldTool(workspace)supported frameworks
packages.
npm packages@tbc-fold/core
runtime-agnostic — workspace, executor, cache, reactive engine, resource interface
@tbc-fold/node
node.js resources — RAM, LocalFS, SQLite, S3, Slack, Ollama, GitHub, Redis
@tbc-fold/mcp
MCP server — expose any workspace to Claude, Cursor, or any MCP client
@tbc-fold/agents
LangChain, LangGraph, Vercel AI SDK adapters
bring your own resource.
extensibilityimport { Resource, Entry, FileStat } from '@tbc-fold/core'
class NotionResource implements Resource {
async list(path: string): Promise<Entry[]> { /* databases as dirs, pages as files */ }
async read(path: string): Promise<Buffer> { /* fetch page content */ }
async write(path: string, data: Buffer) { /* update page */ }
async stat(path: string): Promise<FileStat> { /* check existence */ }
async delete(path: string) { /* archive page */ }
}
const ws = new Workspace({ '/notion': new NotionResource() })five methods. that's the full contract. add subscribe() to make it reactive. add listWithContext() for rich ls -c output.