Catalog PyPI
PACKAGE EXPLORERView in registry

agent-clifs

PyPI

A CLI-driven virtual filesystem for AI agents

Versions collected1
Direct dependencies2From release 1.3.0
Last observed20 Oct, 21:39 UTC

README

Version 1.3.0 documentation

agent-clifs

A virtual filesystem for AI agents. Unix commands they already know. Zero dependencies.


Load documents, codebases, or any text into an in-memory filesystem and let your AI agent explore it with ls, grep, find, tree, and more.

Install

pip install agent-clifs

Quick Start

from agent_clifs import AgentCLI

cli = AgentCLI()

# Load your content
cli.execute("mkdir -p /docs/api")
cli.execute("write /docs/api/users.md '# Users API\nGET /users\nPOST /users'")
cli.execute("write /docs/api/auth.md '# Auth API\nPOST /auth/login'")

# An agent explores just like a developer would
cli.execute("tree /docs")              # See the structure
cli.execute("grep -rn 'POST' /docs")   # Search for patterns
cli.execute("cat /docs/api/users.md")  # Read a file

Bulk Loading

The most common pattern — load from a dictionary:

from agent_clifs import AgentCLI, VirtualFileSystem

vfs = VirtualFileSystem()
vfs.load_from_dict({
    "/src/app.py": "from flask import Flask\napp = Flask(__name__)",
    "/src/models.py": "class User:\n    ...",
    "/docs/setup.md": "# Setup\nRun `pip install -r requirements.txt`",
})

cli = AgentCLI(vfs)
cli.execute("find /src -name '*.py'")

Use with Any Agent Framework

Just pass cli.execute as a tool function:

from langchain.tools import Tool

tool = Tool(
    name="filesystem",
    description="Execute filesystem commands: ls, cat, grep, find, tree, head, tail, wc",
    func=cli.execute,
)

AgentCLI Configuration

AgentCLI(
    vfs=None,
    structured=False,
    readonly=False,
    allowed_commands=None,
    disabled_commands=None,
    bm25_top_files=None,
)
ParameterTypeDefaultDescription
vfsVirtualFileSystem | NoneNoneExisting VFS to use; creates a new empty one if omitted
structuredbool | set[str]FalseLLM-optimized output (see below)
readonlyboolFalseDisable all write commands (write, append, rm, cp, mv, mkdir, touch)
allowed_commandsset[str] | NoneNoneWhitelist of permitted commands; mutually exclusive with disabled_commands
disabled_commandsset[str] | NoneNoneBlacklist of forbidden commands; mutually exclusive with allowed_commands
bm25_top_filesint | NoneNoneEnable BM25 pre-filtering for grep (see below)

structured mode

Controls token-efficient output formatting for LLM consumption:

  • False — raw Unix-style output (default)
  • True — apply LLM formatting to all supported commands: ls, tree, grep, find, wc
  • set[str] — apply formatting only to the specified commands, e.g. structured={"grep", "tree"}
cli = AgentCLI(structured=True)
# grep (standard)                    # grep (structured)
/docs/api/auth.md:3:POST /api/auth   [/docs/api/auth.md]
/docs/api/users.md:3:POST /api/users   L3: POST /api/auth
                                     [/docs/api/users.md]
                                       L3: POST /api/users

BM25 pre-filtering

When working with large codebases, grep -r can search hundreds of files and flood the LLM with results. Setting bm25_top_files builds an in-memory BM25 index over all loaded files and silently restricts each grep call to the top-N most relevant files — the LLM calls grep exactly as it normally would.

vfs = VirtualFileSystem()
vfs.load_from_dict(your_codebase)  # thousands of files

cli = AgentCLI(vfs, bm25_top_files=10)

# The LLM sees normal grep output, but only the 10 most
# relevant files were searched — fewer tokens, less noise.
cli.execute("grep -rn 'def authenticate' /")

The index is built once at initialisation. If you load more files afterwards, call cli.reindex() to rebuild it:

cli = AgentCLI(bm25_top_files=10)
cli.vfs.load_from_dict(more_files)
cli.reindex()

How it works: query terms are extracted from the grep pattern (regex metacharacters are stripped so only literal words remain), files are scored with BM25, and only the top-N are passed to the regex engine. If no literal terms can be extracted from the pattern (e.g. grep -r '.*' /), BM25 filtering is skipped and all files are searched normally.

Command access control

# Only allow read commands
cli = AgentCLI(allowed_commands={"ls", "cat", "grep", "find", "tree", "head", "tail", "wc", "pwd"})

# Or just disable specific ones
cli = AgentCLI(disabled_commands={"rm", "mv"})

# Shorthand for disabling all writes
cli = AgentCLI(readonly=True)

Commands

Pipes (|) and output redirection (>, >>) are supported between commands.

CommandDescriptionKey Flags
lsList directory-l -h -R -S -a -d -1 -r -F
treeDirectory tree-L -d -a
catDisplay files-n -b -s
head / tailFirst/last lines-n -c
grepSearch contents-r -i -n -l -c -v -w -x -F -o -A/-B/-C --include --exclude --max-depth
findFind files/dirs-name -iname -type -path -size -empty -maxdepth -mindepth -delete
sedStream editor-n -e; supports p, d, q, = commands
wcCount lines/words/bytes-l -w -c -m
mkdirCreate directory-p -v
touchCreate empty file-c
writeWrite content to filewrite <path> <content>
appendAppend content to fileappend <path> <content>
cpCopy-r -a -n -v
mvMove/rename-f -n -v
rmRemove-r -f -v
pwd / cdNavigatecd - cd ~

Use cli.help() for full help text, or cli.help("grep") for a specific command.

Python API

Direct access to the underlying VFS:

from agent_clifs import VirtualFileSystem

vfs = VirtualFileSystem()
vfs.load_from_dict({"/file.txt": "hello"})  # bulk load
content = vfs.read_file("/file.txt")         # read
vfs.write_file("/new.txt", "world")          # write
vfs.mkdir("/data", parents=True)             # create directory
snapshot = vfs.to_dict()                     # export as {path: content}

License

Unlicense — public domain.

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Versions 1

Collected releases
VersionPublishedDirect dependenciesOpen version
1.3.05 Apr 20262

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Repository

PENDING
joroden/agent-clifs

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 21:39 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package:5dab296f8d60600ae633c79f43a30a761b98119f7199d7f0c7ed3a1b2c0e1cdd