{"id":"c6668c95-bfe0-49a3-91d8-ec261ed458e4","slug":"aifr","kind":"mcp","name":"aifr","summary":"CLI/MCP/Co-process tool for read-only filesystem & git access","owner":"PennockTech","repoUrl":"https://github.com/PennockTech/aifr","license":"MIT","licenseTier":"permissive","trust":"community","stars":4,"match":null,"fewStars":true,"format":"mcp","createdAt":"2026-03-25T09:46:20.000Z","addedAt":"2026-10-21T17:04:08.629Z","logoUrl":"https://avatars.githubusercontent.com/u/20412531?v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["developer-tools","files-documents"],"tags":["ai-mcp","cli","filesystem","git","read-only"],"runtime":"go","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-26T23:41:39.682Z","sample":false,"url":"https://conduits.dev/tools/aifr","language":"Go","transports":["stdio"],"install":{},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"aifr — AI File Reader\n=====================\n\nA read-only filesystem and git-tree access tool, with both a standalone CLI\nand a JSON-RPC co-process mode which happens to fit the MCP schema for AI\nagents.\n\nAI agents (Claude Code, Cursor, etc.) resort to shell pipelines\n(`sed -n`, `find | grep`, `head/tail`) that trigger security checks and\nproduce brittle, unstructured output. `aifr` replaces all of those with a\nsingle binary that is always safe (never writes) and always scoped (enforces\nallow/deny lists with a built-in sensitive-file blocklist).\n\nThe `aifr` tool can read files, read git state, read \"getent\" system files,\nsome basic system information,  and more.  Everything read-only (except the\nMCP self reload task).  No network access, but some network state querying.\nIt never runs external commands, there is no possibility for shell injection\nattacks.  All functionality is \"native\" to this tool.\n\nA number of filters traditionally done with the Unix pipe handling are moved\nleft into aifr, to limit the output without needing a pipeline.  This avoids\ntriggering security checks for a shell invocation, even when using `aifr`\npurely as a CLI tool, let alone when you start it as a co-process server so\nthat it can quickly answer many questions.  The queries often support options\nto filter which data rows are returned, which columns, to sort, and more.\n\nOutside of AI, scripts which do a lot of git operations often end up\nrepeatedly shelling out to git.  With this agent running as a co-process, they\ncan query configuration and contents and some history with a read-only tool:\nsafe, because it will not touch anything or break the repo; at worst, it will\nfail to parse something, not break your setup.\n\nCombine with tools such as [`ast-grep`](https://ast-grep.github.io) and\n[`ripgrep`](https://github.com/burntsushi/ripgrep).  `aifr` does not seek to\nreplace good tools, it seeks to replace permission-triggering pipeline\ninvocations.\n\n\n## Install\n\nBinary releases are available; currently hosted at:\n<https://github.com/PennockTech/aifr/releases>\n\nOr you can build from source.\n\n```sh\n# From source\ngo install go.pennock.tech/aifr/cmd/aifr@latest\n\n# Or build from the repo\ntask build\n```\n\n### MCP Server for Claude Code\n\n```sh\nclaude mcp add --scope user aifr -- aifr mcp\n```\n\nThis registers `aifr` as an MCP server using stdio transport. Claude Code\nwill then have access to all 20 aifr tools (`aifr_read`, `aifr_cat`,\n`aifr_stat`, `aifr_list`, `aifr_search`, `aifr_find`, `aifr_refs`,\n`aifr_log`, `aifr_diff`, `aifr_wc`, `aifr_hexdump`, `aifr_checksum`,\n`aifr_pathfind`, `aifr_rev_parse`, `aifr_reflog`, `aifr_stash_list`,\n`aifr_sysinfo`, `aifr_getent`, `aifr_git_config`, `aifr_self`).\n\n### Skill File\n\nThe MCP server's built-in instructions are intentionally brief. For richer\nagent guidance (tool routing, advanced patterns, error handling), install the\nskill file:\n\n```sh\n# Symlink into user-level skills (recommended — stays in sync with repo)\nmkdir -p ~/.claude/skills\nln -s \"$(pwd)/skills/aifr\" ~/.claude/skills/aifr\n\n# Or copy if you prefer a snapshot\ncp -r skills/aifr ~/.claude/skills/aifr\n```\n\nYou can also generate the embedded (shorter) skill file at any time:\n\n```sh\naifr skill > /tmp/aifr-skill.md\n```\n\n### HTTP Transport\n\nFor HTTP transport (multi-client setups):\n\n```sh\naifr mcp --transport http --addr :8080\n```\n\n\n## Quick Start\n\n```sh\n# Read a file\naifr read src/main.go\n\n# Read first 50 lines\naifr read --lines 1:50 src/main.go\n\n# Read a file from git history\naifr read HEAD~3:src/main.go\n\n# Concatenate all Go files, skipping vendor\naifr cat --name '*.go' --exclude-path '**/vendor/**' .\n\n# Head: first 10 lines of each Go file with dividers\naifr cat --name '*.go' --lines 10 --divider plain --format text .\n\n# Read with line numbers (like cat -n, but showing actual file line numbers)\naifr read -n src/main.go\naifr read -n --lines 50:100 src/main.go    # lines 50–100, numbered correctly\n\n# Search for a pattern\naifr search 'func.*Handler' ./src/\n\n# Find files by name\naifr find --name '*.yaml' --max-depth 2 .\n\n# List directory\naifr list --depth -1 --type f .\n\n# Git refs and log\naifr refs --branches --tags\naifr log --max-count 5\naifr log --oneline --max-count 10\naifr log --format=text --divider=xml --max-count 3\naifr log --verbose --max-count 1        # tree hash, parent hashes, committer\naifr log v2.12.6..v2.12.7               # range: commits between two tags\naifr log --first-parent main...feature  # symmetric diff, first-parent only\naifr log --grep '^fix:' --since 2024-01-01 HEAD\naifr log --path 'internal/**/*.go' v1.0..HEAD\n\n# Compare files across refs\naifr diff HEAD~1:README.md README.md\n\n# Count lines/words/bytes\naifr wc src/main.go\naifr wc --lines src/*.go              # just line counts\n\n# System databases\naifr getent passwd root\naifr getent passwd --fields name,gecos_name,home\n\n# System inspection\naifr sysinfo --categories os,network\n```\n\nAll commands output JSON by default. Use `--format text` for human-readable\noutput. Line numbering (`-n` / `--number-lines`) is available on `read` and\n`cat` in both formats.\n\n\n### Output Format\n\nThe default output format is JSON. Use `--format text` for human-readable,\ntoken-efficient output suitable for AI agents and shell pipelines.\n\nSet the `AIFR_FORMAT` environment variable to change the default:\n\n```sh\nexport AIFR_FORMAT=text              # all commands default to text\naifr getent passwd root              # text output\naifr getent passwd root --format json  # flag overrides env\n```\n\n`AIFR_FORMAT` accepts a colon-separated preference list — the first format\nsupported by the invoked command wins:\n\n```sh\nexport AIFR_FORMAT=short:text:json   # \"version\" uses short; others use text\n```\n\nInvalid values produce a diagnostic on stderr and exit 64 (`EX_USAGE`).\n\n\n## Configuration\n\nCreate `.aifr.toml` in the working directory or `~/.config/aifr/config.toml`:\n\n```toml\nallow = [\"~/projects/**\"]\ndeny = [\"~/projects/secrets/**\"]\n\n[git.repos]\nmyapp = \"~/projects/myapp\"\n```\n\nIf no config is found, `aifr` operates in \"current directory only\" mode —\nit allows the cwd and everything beneath it.\n\nSee `configs/aifr.example.toml` for the full config reference.\n\n\n## Access Control\n\nEvery path request is evaluated in order:\n\n1. Resolve symlinks to canonical path\n2. **Sensitive list** (built-in, 120+ patterns) → blocked, always\n3. **Deny list** (from config) → blocked\n4. **Allow list** (from config, or cwd fallback) → permitted\n5. **Default** → blocked\n\nSensitive files (SSH keys, cloud credentials, `.env`, shell history, etc.)\nreturn a distinct `ACCESS_DENIED_SENSITIVE` error. The agent is expected to\ntell the user to read the file themselves if needed, and must not retry.\n\nRun `aifr sensitive` to see the full pattern list.\n\n\n## Commands\n\n| Command      | Description                                                 |\n| ------------ | ----------------------------------------------------------- |\n| `read`       | Read file contents (chunked, with continuation tokens)      |\n| `cat`        | Concatenate multiple files with dividers (find+cat in one)  |\n| `stat`       | File/directory metadata                                     |\n| `list`       | Directory listing with depth, pattern, type filters         |\n| `search`     | Content search (RE2 regexp, context lines, include/exclude) |\n| `find`       | Find files by name, type, size, age                         |\n| `diff`       | Compare files or git refs                                   |\n| `wc`         | Count lines, words, and bytes                               |\n| `hexdump`    | Hex dump of file contents                                   |\n| `checksum`   | Compute file checksums                                      |\n| `refs`       | List git branches, tags, remotes                            |\n| `log`        | Git commit log (text/oneline/xml/json, verbose mode)        |\n| `reflog`     | Show git reflog for a ref                                   |\n| `stash-list` | List git stashes                                            |\n| `rev-parse`  | Resolve a git ref to a commit hash                          |\n| `git-config` | Query git configuration                                     |\n| `pathfind`   | Find commands in PATH-like search lists                     |\n| `getent`     | Query system databases (passwd, group, services, protocols) |\n| `sysinfo`    | System inspection for fault diagnosis                       |\n| `config`     | Show effective configuration                                |\n| `sensitive`  | List built-in sensitive file patterns                       |\n| `skill`      | Emit SKILL.md for Claude Code                               |\n| `mcp`        | Start MCP server (stdio or HTTP)                            |\n| `version`    | Print version information                                   |\n\n\n## Git Path Syntax\n\nGit objects are addressed as `[repo:]<ref>:<path>`:\n\n| Input Spec                      | Semantic meaning         |\n| ------------------------------- | ------------------------ |\n| `HEAD:README.md`                | auto-detected repo, HEAD |\n| `main:src/lib.go`               | branch \"main\"            |\n| `v2.0:config.toml`              | tag \"v2.0\"               |\n| `HEAD~3:file.go`                | 3 commits back           |\n| `a1b2c3d:pkg/auth.go`           | short commit hash        |\n| `myrepo:main:terraform/main.tf` | named repo from config   |\n\nAll git reads go directly through the object store — no checkout, no side\neffects on the working tree.\n\n\n## Building\n\n```sh\ntask build              # build with version ldflags\ntask test               # run tests with race detector\ntask check              # fmt + lint + test\ntask release:snapshot   # goreleaser snapshot build\n```\n\nBuild targets: Linux (amd64), macOS (arm64), FreeBSD (amd64).\n\n\n## License\n\n[MIT-style license](LICENSE)\n"}