|
1 | 1 | # aifr — AI File Reader |
2 | 2 |
|
3 | | -Use `aifr` instead of shell pipelines (`sed -n`, `find | grep`, `head/tail`) |
4 | | -for reading files, searching content, and browsing git trees. It is always |
5 | | -safe (read-only) and always scoped (enforces allow/deny lists with a built-in |
6 | | -sensitive-file blocklist). |
7 | | - |
8 | | -## When to Use aifr |
9 | | - |
10 | | -- Reading file contents (instead of `cat`, `head`, `tail`, `sed -n`) |
11 | | -- Searching file content (instead of `grep`, `rg`) |
12 | | -- Finding files by name/pattern (instead of `find`) |
13 | | -- Listing directory contents (instead of `ls`, `find`) |
14 | | -- Getting file metadata (instead of `stat`) |
15 | | -- Reading files from git history without checkout |
16 | | -- Comparing files or git refs (line diff or byte-level cmp) |
17 | | -- Counting lines/words/bytes (instead of `wc`) |
18 | | -- Computing file checksums (instead of `sha256sum`, `md5sum`) |
19 | | -- Hex-dumping binary files (instead of `xxd`, `hexdump`) |
20 | | -- Resolving git refs to commit hashes (instead of `git rev-parse`) |
21 | | -- System inspection: OS, date, hostname, uptime, network, routing (instead of `uname`, `date`, `hostname`, `ip addr`) |
22 | | -- Querying system databases (instead of `getent`, `grep /etc/passwd`, `cut`) |
23 | | - |
24 | | -## CLI Commands |
25 | | - |
26 | | -### Read file contents |
27 | | -``` |
28 | | -aifr read <path> |
29 | | -aifr read --lines 1:50 <path> |
30 | | -aifr read --chunk-id <token> |
31 | | -aifr read HEAD:src/main.go |
32 | | -aifr read myrepo:v2.0:config.toml |
33 | | -``` |
34 | | - |
35 | | -### Concatenate multiple files |
36 | | -``` |
37 | | -aifr cat file1.go file2.go file3.go |
38 | | -aifr cat --format text --divider xml file1.go file2.go |
39 | | -aifr cat --name '*.go' --exclude-path '**/vendor/**' ./src/ |
40 | | -aifr cat --name '*.go' --lines 10 --divider plain --format text . |
41 | | -aifr cat --name '*.yaml' --max-depth 2 ./config/ |
42 | | -``` |
43 | | - |
44 | | -### Get file/directory metadata |
45 | | -``` |
46 | | -aifr stat <path> |
47 | | -aifr stat HEAD:README.md |
48 | | -``` |
49 | | - |
50 | | -### List directory |
51 | | -``` |
52 | | -aifr list <path> |
53 | | -aifr list --depth -1 <path> |
54 | | -aifr list --pattern "*.go" --type f <path> |
55 | | -aifr list HEAD:src/ |
56 | | -``` |
57 | | - |
58 | | -### Search content (grep-like) |
59 | | -``` |
60 | | -aifr search "pattern" <path> |
61 | | -aifr search --fixed-string "exact text" <path> |
62 | | -aifr search --ignore-case --context 2 "TODO" <path> |
63 | | -aifr search --include "*.go" "func.*Handler" ./ |
64 | | -``` |
65 | | - |
66 | | -### Find files |
67 | | -``` |
68 | | -aifr find --name "*.go" <path> |
69 | | -aifr find --type f --min-size 1024 <path> |
70 | | -aifr find --newer-than 24h <path> |
71 | | -``` |
72 | | - |
73 | | -### Git refs and log |
74 | | -``` |
75 | | -aifr refs |
76 | | -aifr refs --branches --tags |
77 | | -aifr refs /path/to/repo |
78 | | -aifr log --max-count 10 |
79 | | -aifr log HEAD |
80 | | -aifr log /path/to/repo:main |
81 | | -``` |
82 | | - |
83 | | -### Compare files |
84 | | -``` |
85 | | -aifr diff file1.go file2.go |
86 | | -aifr diff --cmp file1.bin file2.bin # byte-level comparison |
87 | | -aifr diff HEAD~1:main.go main.go |
88 | | -aifr diff main:lib.go feature:lib.go |
89 | | -``` |
90 | | - |
91 | | -### Count lines/words/bytes |
92 | | -``` |
93 | | -aifr wc file.go |
94 | | -aifr wc -l *.go |
95 | | -aifr wc --total-only -l src/**/*.go # combined total only |
96 | | -aifr wc HEAD:README.md |
97 | | -``` |
98 | | - |
99 | | -### File checksums |
100 | | -``` |
101 | | -aifr checksum file.go |
102 | | -aifr checksum -a sha512 *.go |
103 | | -aifr checksum -a sha3-256 -e base64 file.go |
104 | | -aifr checksum HEAD:README.md |
105 | | -``` |
106 | | - |
107 | | -### Hex dump |
108 | | -``` |
109 | | -aifr hexdump binary.dat |
110 | | -aifr hexdump -s 1024 -l 512 binary.dat # offset + length |
111 | | -aifr hexdump HEAD:binary.dat |
112 | | -``` |
113 | | - |
114 | | -### Git reflog |
115 | | -``` |
116 | | -aifr reflog # HEAD reflog |
117 | | -aifr reflog main # branch reflog |
118 | | -aifr reflog --max-count 10 HEAD |
119 | | -``` |
120 | | - |
121 | | -### Git stash list |
122 | | -``` |
123 | | -aifr stash-list |
124 | | -aifr stash-list --max-count 5 |
125 | | -``` |
126 | | - |
127 | | -### Resolve git refs |
128 | | -``` |
129 | | -aifr rev-parse HEAD |
130 | | -aifr rev-parse main |
131 | | -aifr rev-parse --repo myrepo v2.0 |
132 | | -aifr rev-parse HEAD~3 |
133 | | -``` |
134 | | - |
135 | | -### System inspection |
136 | | -``` |
137 | | -aifr sysinfo |
138 | | -aifr sysinfo --sections date # just date/time |
139 | | -aifr sysinfo --sections os,hostname,uptime |
140 | | -``` |
141 | | - |
142 | | -### Git config |
143 | | -``` |
144 | | -aifr git-config remote.origin.url # local key lookup |
145 | | -aifr git-config --scope merged user.email # merged with includes |
146 | | -aifr git-config --identity # structured identity (merged) |
147 | | -aifr git-config --remotes # structured remotes |
148 | | -aifr git-config --branches # structured branches |
149 | | -aifr git-config --regexp 'branch\..*\.remote' # pattern match |
150 | | -aifr git-config --section remote.origin # section listing |
151 | | -aifr git-config --list --scope local # dump local config |
152 | | -``` |
153 | | - |
154 | | -### Query system databases |
155 | | -``` |
156 | | -aifr getent passwd # all users |
157 | | -aifr getent passwd root # lookup by name |
158 | | -aifr getent passwd 1000 # lookup by UID |
159 | | -aifr getent passwd --fields name,uid,home # field selection |
160 | | -aifr getent group docker # group lookup |
161 | | -aifr getent services --fields name,port 443 # service by port |
162 | | -``` |
163 | | - |
164 | | -### Find commands in PATH |
165 | | -``` |
166 | | -aifr pathfind git |
167 | | -aifr pathfind 'git-*' |
168 | | -aifr pathfind python3 --search-list 'envvar:PATH' |
169 | | -aifr pathfind javac --search-list 'dirlist:/usr/lib/jvm/bin:/usr/bin' |
170 | | -``` |
171 | | - |
172 | | -### Other |
173 | | -``` |
174 | | -aifr config # show effective configuration |
175 | | -aifr sensitive # list sensitive file patterns (for auditing) |
176 | | -aifr version # version info |
177 | | -``` |
178 | | - |
179 | | -## Git Path Syntax |
180 | | - |
181 | | -Git objects are addressed as `[repo:]<ref>:<path>`: |
182 | | -- `HEAD:README.md` — HEAD of auto-detected repo |
183 | | -- `main:src/lib.go` — main branch |
184 | | -- `v2.0:config.toml` — tag v2.0 |
185 | | -- `HEAD~3:file.go` — 3 commits back |
186 | | -- `myrepo:main:src/` — named repo "myrepo" at branch main |
187 | | -- `/path/to/repo:HEAD:README.md` — repo at filesystem path |
188 | | - |
189 | | -## Chunked Reading |
190 | | - |
191 | | -Large files are returned in chunks. Use the continuation token to read more: |
192 | | -1. `aifr read large-file.log` → returns first chunk + `continuation` token |
193 | | -2. `aifr read --chunk-id <token>` → returns next chunk |
194 | | -3. Repeat until `"complete": true` |
195 | | - |
196 | | -## Error Handling |
197 | | - |
198 | | -- `ACCESS_DENIED_SENSITIVE` — file matches sensitive pattern (credentials, keys, etc.). |
199 | | - Do NOT retry. Ask the user to read it manually if needed. |
200 | | -- `ACCESS_DENIED` — path is outside allow-list or in deny-list. |
201 | | -- `NOT_FOUND` — path does not exist. |
202 | | -- `STALE_CONTINUATION` — file changed since continuation token was issued. Re-read from start. |
203 | | - |
204 | | -## Output |
205 | | - |
206 | | -All commands output JSON by default. Use `--format text` for human-readable output. |
207 | | - |
208 | | -## MCP Server |
209 | | - |
210 | | -`aifr mcp` starts the MCP server (stdio by default). The same operations are |
211 | | -available as MCP tools: `aifr_read`, `aifr_cat`, `aifr_stat`, `aifr_list`, |
212 | | -`aifr_search`, `aifr_find`, `aifr_refs`, `aifr_log`, `aifr_diff`, |
213 | | -`aifr_pathfind`, `aifr_wc`, `aifr_checksum`, `aifr_hexdump`, |
214 | | -`aifr_rev_parse`, `aifr_sysinfo`, `aifr_getent`, `aifr_reflog`, |
215 | | -`aifr_stash_list`, `aifr_self`, `aifr_git_config`. |
216 | | - |
217 | | -For `aifr_cat`, use `format="text"` with `divider="xml"` for token-efficient |
218 | | -multi-file reading with `<file path="...">` wrappers. |
| 3 | +Read-only access to filesystem, git trees, and system state. |
| 4 | +All aifr_* tool calls are permission-free — no Bash approval prompts. |
| 5 | + |
| 6 | +## Routing Rules |
| 7 | + |
| 8 | +ALWAYS prefer aifr_* tools over Bash for read-only operations. |
| 9 | + |
| 10 | +| Instead of | Use | |
| 11 | +|---|---| |
| 12 | +| `cat`, `head`, `tail`, `sed -n` | `aifr_read` | |
| 13 | +| reading 2+ files separately | `aifr_cat` (one call) | |
| 14 | +| `ls`, `tree` | `aifr_list` | |
| 15 | +| `grep -r`, `rg` | `aifr_search` | |
| 16 | +| `find` | `aifr_find` | |
| 17 | +| `stat` | `aifr_stat` | |
| 18 | +| `diff` | `aifr_diff` | |
| 19 | +| `wc` | `aifr_wc` | |
| 20 | +| `sha256sum`, `md5sum` | `aifr_checksum` | |
| 21 | +| `xxd`, `hexdump` | `aifr_hexdump` | |
| 22 | +| `git log` | `aifr_log` | |
| 23 | +| `git branch`, `git tag` | `aifr_refs` | |
| 24 | +| `git show <ref>:<path>` | `aifr_read` with ref:path | |
| 25 | +| `git diff <ref>` | `aifr_diff` with ref:paths | |
| 26 | +| `git rev-parse` | `aifr_rev_parse` | |
| 27 | +| `git reflog` | `aifr_reflog` | |
| 28 | +| `git stash list` | `aifr_stash_list` | |
| 29 | +| `git config` | `aifr_git_config` | |
| 30 | +| `uname`, `date`, `hostname`, `uptime` | `aifr_sysinfo` | |
| 31 | +| `ip addr`, `ip route` | `aifr_sysinfo` (sections: network, routing) | |
| 32 | +| `getent`, `grep /etc/passwd`, `id` | `aifr_getent` | |
| 33 | +| `which`, `command -v`, `type -p` | `aifr_pathfind` | |
| 34 | + |
| 35 | +### Pipeline detection |
| 36 | + |
| 37 | +If you are about to construct a shell pipeline (`|`), stop — aifr handles it |
| 38 | +in one call. Examples: `find | xargs grep` → `aifr_search` with `include`, |
| 39 | +`find | xargs cat` → `aifr_cat` with `name`, `cat | head -N` → `aifr_read` |
| 40 | +with `lines`, `cat | wc` → `aifr_wc`, `git log | head` → `aifr_log` with |
| 41 | +`max_count`, `ls | sort` → `aifr_list` with `sort`, `cat /etc/passwd | grep` |
| 42 | +→ `aifr_getent` with `key`. |
| 43 | + |
| 44 | +### With built-in Read / Grep / Glob tools |
| 45 | + |
| 46 | +- **Prefer aifr_read** for: git ref paths (`HEAD:file.go`), line ranges, chunked large files |
| 47 | +- **Prefer aifr_cat** over multiple Read calls when reading 2+ related files |
| 48 | +- **Always use aifr** for: git ops, system queries, diff, wc, checksum, hexdump (no built-in equivalent) |
| 49 | +- Built-in Read/Grep/Glob remain fine for simple single-file reads and basic searches |
| 50 | + |
| 51 | +## Git Ref Path Syntax |
| 52 | + |
| 53 | +`[repo:]<ref>:<path>` — reads from git object store, no checkout. |
| 54 | +Examples: `HEAD:README.md`, `main:src/lib.go`, `v2.0:config.toml`, `HEAD~3:file.go`, `myrepo:main:src/` |
| 55 | + |
| 56 | +## Key Patterns |
| 57 | + |
| 58 | +**Multi-file**: `aifr_cat(root=".", name="*.go", format="text", divider="xml")` → `<file path="...">content</file>` per file. Use `lines` for head mode, `exclude_path` to skip directories. |
| 59 | + |
| 60 | +**Chunked read**: `aifr_read(path=...)` → get continuation token → `aifr_read(path=..., chunk_id="<token>")` → repeat until `complete: true`. |
| 61 | + |
| 62 | +**Git config**: `structured="identity"` for name/email, `structured="remotes"`, `structured="branches"`. Use `scope="merged"` for full cascade with gitdir: includes. |
| 63 | + |
| 64 | +**System info**: `aifr_sysinfo(sections=["date"])` for current date/time/year. Sections: os, date, hostname, uptime, network, routing. |
| 65 | + |
| 66 | +## Errors |
| 67 | + |
| 68 | +- `ACCESS_DENIED_SENSITIVE` — credential file. **Do NOT retry.** Tell user to read manually. |
| 69 | +- `STALE_CONTINUATION` — file changed since chunk issued. Re-read from start. |
| 70 | +- `ACCESS_DENIED` — outside allow-list. `NOT_FOUND` — path doesn't exist. |
0 commit comments