Skip to content

mwolting/context-fs

Repository files navigation

context-fs

Expose context to AI agents as a dynamic filesystem.

AI coding agents already know how to navigate filesystems - ls, cat, find, symlinks. context-fs lets you expose your APIs, databases, and services using an interface they already understand.

/linear
├── issues/
│   ├── by-id/
│   │   └── ENG-123/
│   │       ├── content.md      # Read/write issue content
│   │       ├── team -> /teams/engineering
│   │       └── assignee -> /users/alice
│   └── search/
│       └── auth%20bug/         # Search results as symlinks
├── teams/
│   └── engineering/
│       ├── info.json
│       └── issues/
│           ├── active/         # Symlinks to open issues
│           └── triage/
└── users/
    └── alice/
        ├── info.json
        └── issues/
            └── assigned/       # Symlinks to assigned issues
Screen.Recording.2026-01-10.at.18.33.25.mov

Packages

Package Description
@context-fs/core Virtual filesystem core - define trees with handlers
@context-fs/nfs Mount as NFS - appears as real directory
@context-fs/cli CLI framework for building context-fs tools
@context-fs/linear Linear issue tracker as a filesystem
@context-fs/just-bash Run bash scripts against virtual filesystems

Quick Start

Use an existing filesystem

# Mount your Linear workspace
npx @context-fs/linear --mount /tmp/linear

# Agent can now explore
ls /tmp/linear/teams/
cat /tmp/linear/issues/by-id/ENG-123/content.md
ls /tmp/linear/issues/search/authentication%20bug/

Build your own

import { createFileSystem, read, list, link } from "@context-fs/core";
import { mount } from "@context-fs/nfs";

const vfs = createFileSystem({
  projects: {
    ":projectId": {
      [list]: () => getProjects().map((p) => ({ projectId: p.id })),

      "readme.md": {
        [read]: (c) => getProjectReadme(c.params.projectId),
      },

      tasks: {
        ":taskId": {
          [list]: (c) =>
            getTasks(c.params.projectId).map((t) => ({ taskId: t.id })),

          "content.md": {
            [read]: (c) => getTaskContent(c.params.projectId, c.params.taskId),
          },

          // Symlink to the assignee
          assignee: {
            [link]: (c) => {
              const task = getTask(c.params.taskId);
              return `/users/${task.assigneeId}`;
            },
          },
        },
      },
    },
  },

  users: {
    ":userId": {
      [list]: () => getUsers().map((u) => ({ userId: u.id })),
      "profile.json": {
        [read]: (c) => c.json(getUser(c.params.userId)),
      },
    },
  },
});

await using handle = await mount(vfs, { mountPoint: "/tmp/projects" });

Now an agent can:

# Discover available projects
ls /tmp/projects/projects/

# Read a project overview
cat /tmp/projects/projects/website-redesign/readme.md

# List tasks
ls /tmp/projects/projects/website-redesign/tasks/

# Read a specific task
cat /tmp/projects/projects/website-redesign/tasks/implement-auth/content.md

# Follow the assignee symlink to learn about who's working on it
cat /tmp/projects/projects/website-redesign/tasks/implement-auth/assignee/profile.json

Key Concepts

Dynamic paths with list

The list handler tells the filesystem what entries exist in a dynamic directory:

{
  ":issueId": {
    [list]: async () => {
      const issues = await fetchIssues();
      return issues.map(i => ({ issueId: i.id }));
    },
    "content.md": {
      [read]: (c) => getIssue(c.params.issueId).description,
    },
  },
}

Relationships with symlinks

Use the link handler to express relationships as symlinks:

{
  "author": {
    [link]: (c) => `/users/${getPost(c.params.postId).authorId}`,
  },
  "related": {
    ":relatedId": {
      [list]: (c) => getRelatedPosts(c.params.postId).map(p => ({ relatedId: p.id })),
      [link]: (c) => `/posts/${c.params.relatedId}`,
    },
  },
}

Write support

Enable agents to make changes with the write handler:

{
  "content.md": {
    [read]: (c) => getContent(c.params.id),
    [write]: async (c, data) => {
      const text = new TextDecoder().decode(data);
      await updateContent(c.params.id, text);
      return {}; // Success
    },
  },
}

Installation

# Core library (browser-safe)
npm install @context-fs/core

# With NFS mounting (Node.js)
npm install @context-fs/core @context-fs/nfs

# CLI framework for building tools
npm install @context-fs/cli

Development

bun install          # Install dependencies
bun run build        # Build all packages
bun run check        # Run prettier, oxlint, typescript
bun run fix          # Fix formatting and lint issues

Creating a Release

bun changeset                    # Describe your changes
git add .changeset/*.md
git commit -m "feat: add feature"
git push                         # CI creates release PR

License

MIT

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •