About
Experience
worked as - Founder & Lead Developer
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 per source. One tool.
Building 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.
import { 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')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.
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.
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.
┌──────────────────────────────────────────────────────────┐
│ 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.
Pipes (`|`), output redirects (`>`, `>>`), and quoted strings all work. No shell subprocess — everything runs in-process.
fold exposes any workspace as an MCP server out of the box. One file. Your data is available everywhere MCP runs — Claude, Cursor, or any MCP client.
// 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)fold integrates with LangChain, LangGraph, and Vercel AI SDK out of the box via the `@tbc-fold/agents` package.
import { 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.