Mount anything, shell everything. A virtual userland that unifies heterogeneous data sources — files, databases, APIs, memory, tools — into one filesystem namespace. Agents ls, cat, grep, and pipe their way through the world.
/
├── data/ → LocalFS (host directory)
├── memory/ → MemFS (in-memory storage)
├── tools/mcp/ → MCPToolProvider (external tools)
├── knowledge/ → your custom provider
└── proc/ → ProcProvider (system info)
- One verb to access everything.
readworks on local files, databases, APIs, and memory — the agent doesn't care what's behind the mount point. - Not restricting — reframing. GRASP doesn't take capabilities away from agents. It gives them a better interface. Linux "restricts" programs from touching hardware directly — and makes them more powerful for it.
- LLMs speak filesystem natively. Training data is saturated with
ls,cat,grep,echo. File operations are the one interface every LLM already understands. Meet them where they are. - Mount what matters, hide what doesn't. An agent that sees the entire OS gets lost. An agent that sees
/workspace,/memory,/toolsknows exactly what to do. Mounting is attention management. - Same agent, different world. Swap mount tables, not code. Dev, CI, sandbox, remote — the agent logic never changes.
- Safety is a side effect of good design. Capability-based access control and mount isolation aren't the selling point — they're a natural consequence of the abstraction.
- The composable middle layer. Not a framework (above), not a storage engine (below). The runtime between them that makes everything interoperable.
Agent frameworks give LLMs tools through JSON schemas — read_file, write_file, search_files, one API per operation. This works, but it fragments: tools don't compose, data sources have separate interfaces, and every new source means new schemas.
Unix solved this 50 years ago: everything is a file. Mount a data source, then use standard commands to operate on it. GRASP brings this to agents — one shell tool replaces dozens of individual tool definitions.
# One tool call, not five
cat /data/logs/2026-02-*.md | grep ERROR | head -10The AI agent infrastructure space is growing fast. Here's where GRASP sits:
| Project | What it is | GRASP difference |
|---|---|---|
| OpenClaw | Full agent runtime (TS, 182K stars). Gives agents shell, browser, filesystem via built-in tools. | OpenClaw is a complete agent; GRASP is an embeddable layer. OpenClaw's tools are hardcoded to the host OS — GRASP virtualizes and composes across mount points. Can serve as OpenClaw's MCP backend. |
| Turso AgentFS | SQLite-backed agent filesystem (Rust). Copy-on-write isolation, audit logging, single-file snapshots. | AgentFS isolates file access; GRASP unifies heterogeneous sources. AgentFS has no shell, no pipes, no mount composition. Complementary — dbfs could wrap AgentFS. |
| OpenViking | Context database (Python, ByteDance). viking:// protocol, L0/L1/L2 tiered loading, semantic retrieval. |
OpenViking is a storage backend with vector search; GRASP is a runtime with shell. Not competitors — OpenViking can be mounted as a GRASP provider, combining semantic retrieval with shell composability. |
| ToolFS | FUSE-based VFS for agents (Go, IceWhaleTech). Unified /toolfs namespace, WASM skills, RAG. |
Both are Go VFS projects. ToolFS requires FUSE (kernel module); GRASP is pure userspace with protocol-native access (MCP, 9P). ToolFS bundles RAG/skills; GRASP keeps the core minimal and mounts them as providers. |
| AIOS | LLM OS kernel (Python, academic). Agent scheduling, context switching, memory management. | AIOS is a research OS that manages multiple agents; GRASP is a practical runtime for individual agents. AIOS handles scheduling and resource allocation — concerns GRASP intentionally leaves to the host. |
| Agent OS | Self-evolving agent runtime (Rust). AIR typed control plane, capability security, constitutional self-modification. | Agent OS focuses on agent self-modification and governance; GRASP focuses on data access and tool composition. Different layers — Agent OS could use GRASP as its filesystem substrate. |
| MCP FS Server | Exposes host files as MCP tools (Go/TS). read_file, write_file, search_files. |
Flat tool list for one directory. GRASP virtualizes: mount multiple sources, compose via shell pipes, search across mounts. One shell tool replaces the entire tool list. |
TL;DR: Most projects are either full agent runtimes (OpenClaw, AIOS) or single-purpose storage (AgentFS, OpenViking). GRASP is the composable middle layer — a virtual userland that any agent can embed, mount anything into, and operate through a shell. Think Docker for agent context: it doesn't replace your app, it gives it a portable, composable runtime.
go get github.com/jackfish212/grasp@latestRequires Go 1.24+. The only external dependency is modernc.org/sqlite (pure Go, no CGO).
package main
import (
"context"
"fmt"
"github.com/jackfish212/grasp"
"github.com/jackfish212/grasp/builtins"
"github.com/jackfish212/grasp/mounts"
)
func main() {
v := grasp.New()
rootFS, _ := grasp.Configure(v)
builtins.RegisterBuiltinsOnFS(v, rootFS)
v.Mount("/data", mounts.NewLocalFS(".", grasp.PermRW))
sh := v.Shell("agent")
ctx := context.Background()
result := sh.Execute(ctx, "ls /data")
fmt.Print(result.Output)
}Every data source implements the Provider interface (just Stat + List) and gets mounted at a path. Additional capabilities are expressed as optional interfaces, detected at runtime via type assertions:
| Interface | Methods | Purpose |
|---|---|---|
Provider |
Stat, List |
Navigation (required) |
Readable |
Open |
Read file content |
Writable |
Write |
Create/update files |
Executable |
Exec |
Run tools & commands |
Searchable |
Search |
Full-text or semantic search |
Mutable |
Mkdir, Remove, Rename |
Namespace changes |
Providers only implement what they support — no stub methods, no unused interfaces.
| Provider | Capabilities | Description |
|---|---|---|
MemFS |
R/W/X/Mut | In-memory filesystem; register Go functions as commands |
LocalFS |
R/W/S/Mut | Mount a host directory |
MCPToolProvider |
R/X/S | Bridge MCP server tools as executable entries |
MCPResourceProvider |
R/S | Bridge MCP server resources as readable entries |
VikingProvider |
R/W/S/Mut | Bridge OpenViking context database with L0/L1/L2 tiered loading |
Agents interact through a shell with pipes, redirects, logical operators, here-documents, and environment variables:
ls /data # browse
cat /data/config.yaml # read
echo "done" > /memory/log.md # write (redirect)
search "auth" --scope /knowledge # cross-mount search
cat /data/users.json | grep admin # pipes
mkdir /tmp/work && cd /tmp/work # logical operators
cat << EOF | write /memory/note.md # here-documents
Meeting notes from today.
EOFBuilt-in commands: ls, cat, read, write, stat, search, grep, find, head, tail, mkdir, rm, mv, which, mount, uname
Shell builtins: cd, pwd, echo, env, history
Implement Provider + whichever capability interfaces fit your data source:
type WikiProvider struct{ /* ... */ }
func (w *WikiProvider) Stat(ctx context.Context, path string) (*grasp.Entry, error) { /* ... */ }
func (w *WikiProvider) List(ctx context.Context, path string, opts grasp.ListOpts) ([]grasp.Entry, error) { /* ... */ }
func (w *WikiProvider) Open(ctx context.Context, path string) (grasp.File, error) { /* ... */ }
func (w *WikiProvider) Search(ctx context.Context, q string, opts grasp.SearchOpts) ([]grasp.SearchResult, error) { /* ... */ }
v.Mount("/wiki", &WikiProvider{})
// Now: cat /wiki/Go_(programming_language) | head -20Register Go functions as executable commands on any MemFS:
rootFS.AddExecFunc("usr/bin/greet", func(ctx context.Context, args []string, stdin io.Reader) (io.ReadCloser, error) {
name := "world"
if len(args) > 0 {
name = args[0]
}
return io.NopCloser(strings.NewReader("Hello, " + name + "!\n")), nil
}, mounts.FuncMeta{Description: "Greet someone", Usage: "greet [name]"})GRASP is not an agent framework — it's the runtime layer underneath. Expose the same VirtualOS instance through multiple protocols:
| Protocol | Use case | Status |
|---|---|---|
| Go SDK | Embed directly in Go agent code | Available |
| MCP Server | Connect to Claude Desktop, Cursor, or any MCP client | Available |
| 9P Server | Cross-language POSIX access — mount -t 9p then use standard file I/O from Python, Rust, etc. |
Planned |
Install and run:
go install github.com/jackfish212/grasp/cmd/grasp-server@latest
grasp-server --mount /data:./workspace --mount /memory:memfsConfigure in Claude Desktop (claude_desktop_config.json) or any MCP client:
{
"mcpServers": {
"grasp": {
"command": "grasp-server",
"args": ["--mount", "/data:./workspace", "--mount", "/memory:memfs"]
}
}
}The agent gets a single shell tool — one tool replaces dozens:
shell("cat /data/src/main.go | grep TODO")
shell("ls /data && search 'authentication' --scope /data --max 5")
shell("echo 'task done' >> /memory/log.md")
Mount sources:
--mount /path:./dir— host directory (LocalFS)--mount /path:memfs— in-memory (MemFS)
Mount OpenViking as a provider to combine semantic retrieval with the shell interface:
import "github.com/jackfish212/grasp/mounts"
client := mounts.NewVikingClient("http://localhost:1933", "your-api-key")
v.Mount("/ctx", mounts.NewVikingProvider(client, ""))ls /ctx/resources/ # browse context tree
cat /ctx/resources/project/.abstract # L0: ~100 tokens summary
cat /ctx/resources/project/.overview # L1: ~2K tokens overview
cat /ctx/resources/project/docs/api.md # L2: full content
search "auth flow" --scope /ctx # directory-recursive semantic search
echo "https://example.com/doc.md" > /ctx/resources/new_doc # add resourcegrasp/
├── vos.go # VirtualOS — central orchestrator
├── mount_table.go # Path → Provider resolution (longest-prefix matching)
├── configure.go # Standard filesystem layout (/bin, /etc, /proc, ...)
├── exports.go # Public API re-exports
├── types/ # Core interfaces: Provider, Entry, File, Perm, ...
├── mounts/ # Built-in providers: MemFS, LocalFS, MCP
├── builtins/ # Commands: ls, cat, grep, search, find, ...
├── shell/ # Shell: pipes, redirects, env, history, profile
├── mcpserver/ # MCP server: expose VirtualOS as MCP tools over stdio
├── cmd/grasp-server/ # Standalone MCP server binary
├── docs/ # Documentation
└── examples/ # Example applications
The examples/ directory contains complete working examples demonstrating GRASP's capabilities:
| Example | Description | Key Features |
|---|---|---|
| agent-monitor | AI agent monitors user shell activity and offers contextual help when commands fail or files change | VOS.Watch() for file change notifications, Shell.OnExec() for command hooks, event-driven agent responses |
| multi-agent | Three agents (Explorer → Architect → Reporter) collaborate through shared filesystem to analyze a codebase | Multi-agent coordination via files, isolated shells with shared mounts, pipeline architecture |
| cached-feeds | Demonstrates union mount caching with dbfs over httpfs, showing latency improvements and offline resilience | Union mount composition, cache TTL, performance comparison |
| custom-mount | Build a custom provider that bridges external data sources into the VFS | Provider interface implementation, capability-based design |
| full-demo | Comprehensive demo showing multiple providers, MCP integration, and shell operations | End-to-end integration example |
| github-mcp | Mount GitHub as an MCP tool provider, exposing repository operations as executable commands | MCP tool bridging, external API integration |
| anthropic | Integrate Anthropic's Claude API with GRASP's shell interface | LLM integration, tool use patterns |
Each example includes inline documentation and can be run with go run ./examples/<name>.
See docs/ for full documentation:
- Why GRASP — Problem statement, naming rationale, positioning, comparisons
- Architecture — VirtualOS, MountTable, Shell internals
- Provider Model — Capability-based interface design
- Shell as Interface — Why shell beats tool APIs for agents
- Integration Strategy — MCP, 9P, OpenViking
- Getting Started — Step-by-step tutorial
- Create a Provider — Build your own data source
- Interface Reference — Complete API reference
MIT
