16 standalone UNIX utilities written in V — bridging the gap between Windows and UNIX shell environments for AI agents and developer tools.
- Why This Exists
- Quick Start
- Tool Reference
- Argument Policy
- Testing
- Architecture
- Building
- RTK on Windows — Agent Prompt Template
Windows lacks native equivalents of standard UNIX commands (ls, grep, find, etc.). While PowerShell provides aliases, they are incompatible with external programs that expect real executables on PATH.
Built for rtk
The core motivation is token economy for AI agents. When an LLM calls PowerShell cmdlets like Select-String or Get-ChildItem, the output is verbose, object-formatted, and often hundreds of lines. This wastes thousands of tokens per call — tokens you pay for.
These executables produce dense, UNIX-style plain-text output consumable in a single glance. Paired with rtk (AI proxy), they let agents execute CLI operations with short pipelines like:
rtk grep -n "pattern" path | rtk head -n 80
rtk findd ./src -name "*.ts" | xargs grep "TODO" | rtk head -n 200To get the most out of this setup, use the agent system prompt provided in AGENTS_SUGGESTION_FOR_RTK.md. It enforces mandatory rtk wrappers, forbids verbose PowerShell cmdlets, and auto-excludes binary/dependency directories — all designed to minimize token waste.
The binaries:
- Work as real executables — callable from any shell, script, or external tool (e.g.,
rtk, AI agents like Codex/Gemini) - Return POSIX exit codes —
0for success,1for no match/error,2for usage errors - Support common GNU/UNIX flags — progressively implementing the most-used flags
- Handle Windows paths — backslash/forward-slash normalization,
PATHEXTsupport - Auto-exclude noisy directories —
node_modules,.git,vendor, etc. are skipped by default in recursive scans - Auto-detect literal patterns — grep bypasses the regex engine when the pattern has no meta-characters, cutting RAM from GBs to MBs
- V compiler installed and on PATH
cd executables
.\build.bat
# or
powershell -File .\build.ps1cd executables\exe_ls
.\build.batBinaries are compiled to the project root (two levels above each exe_<tool> directory). Place them in a directory on your PATH.
ls -la .
grep -rn "TODO" ./src --include="*.v"
find . -iname "*.txt" -type f
cat -n file.txt | head -n 20
sort data.csv | uniq -cls [OPTIONS] [FILE...]
| Flag | Description |
|---|---|
-a, --all |
Show hidden files (starting with .) |
-A, --almost-all |
Like -a but exclude . and .. |
-l, --long |
Long listing format with permissions, size, date |
-h, --human-readable |
Human-readable sizes (1K, 234M, 2G) with -l |
--si |
Like -h but use powers of 1000 |
-r, --reverse |
Reverse sort order |
-R, --recursive |
List subdirectories recursively |
-1, --one-line |
One file per line |
-m, --commas |
Comma-separated list |
-S |
Sort by file size (largest first) |
-t |
Sort by modification time (newest first) |
-v |
Natural sort of version numbers (file2 before file10) |
-X |
Sort alphabetically by extension |
-U |
Do not sort (directory order) |
-F, --classify |
Append indicator (`*/=>@ |
-p, --slash |
Append / to directories |
--group-directories-first |
Group directories before files |
-i, --inode |
Print inode number |
-s, --size |
Print allocated size in blocks |
-n, --numeric-uid-gid |
Numeric user/group IDs |
-g, --no-owner |
Like -l but hide owner |
-G, --no-group |
Hide group in long listing |
-o |
Like -l but hide group |
-d, --directory |
List directories themselves, not contents |
-Q, --quote-name |
Enclose names in double quotes |
-b, --escape |
C-style escapes for non-graphic characters |
--color=WHEN |
Colorize output (always, auto, never) |
--time-style=STYLE |
Time format (full-iso, long-iso, iso, locale) |
--full-time |
Like -l --time-style=full-iso |
-u |
Sort/show access time |
-c |
Sort/show status change time |
pwd [OPTIONS]
| Flag | Description |
|---|---|
-L |
Use PWD from environment (default) |
-P |
Resolve all symlinks (stub) |
Outputs forward-slash paths for UNIX compatibility.
which [OPTIONS] COMMAND...
| Flag | Description |
|---|---|
-a, --all |
Print all matching pathnames |
Searches PATH directories and respects PATHEXT on Windows.
cat [OPTIONS] [FILE...]
| Flag | Description |
|---|---|
-n, --number |
Number all output lines |
-b, --number-nonblank |
Number non-empty lines only (overrides -n) |
-s, --squeeze-blank |
Suppress repeated empty lines |
-E, --show-ends |
Display $ at end of each line |
-T, --show-tabs |
Display TAB as ^I |
-A, --show-all |
Equivalent to -vET |
Reads from stdin when no file is specified or file is -.
head [OPTIONS] [FILE...]
| Flag | Description |
|---|---|
-n K, --lines=K |
Print first K lines (default: 10) |
-c K, --bytes=K |
Print first K bytes |
-v, --verbose |
Always print file name headers |
-q, --quiet |
Never print file name headers |
tail [OPTIONS] [FILE...]
| Flag | Description |
|---|---|
-n K, --lines=K |
Output last K lines (default: 10) |
-f, --follow |
Output appended data as file grows |
-s N, --sleep-interval=N |
Sleep N seconds between follow iterations |
-v, --verbose |
Always print file name headers |
-q, --quiet |
Never print file name headers |
Performance: Uses seek-from-end approach — handles multi-GB files without loading them into memory.
grep [OPTIONS] PATTERN [FILE...]
| Flag | Description |
|---|---|
-i, --ignore-case |
Case-insensitive matching |
-v, --invert-match |
Select non-matching lines |
-n, --line-number |
Print line numbers |
-c, --count |
Print only match count per file |
-l, --files-with-matches |
Print only filenames with matches |
-L, --files-without-matches |
Print only filenames without matches |
-r, -R, --recursive |
Search directories recursively |
-w, --word-regexp |
Match whole words only |
-x, --line-regexp |
Match whole lines only |
-F, --fixed-strings |
Treat pattern as literal string |
-o, --only-matching |
Show only the matched part of lines |
-H, --with-filename |
Print filename with output |
-h, --no-filename |
Suppress filename prefix |
-A N, --after-context=N |
Print N lines after each match |
-B N, --before-context=N |
Print N lines before each match |
-C N, --context=N |
Print N lines of context (before + after) |
-m N, --max-count=N |
Stop after N matches per file |
-q, --quiet |
Suppress all output |
-s, --silent |
Suppress error messages |
--color=WHEN |
Colorize matches (always, auto, never) |
--exclude=GLOB |
Skip files matching GLOB |
--exclude-dir=DIR |
Skip directories matching DIR |
--include=GLOB |
Search only files matching GLOB |
Performance: Auto-detects literal patterns to bypass the regex engine, circular buffer for context lines (O(1) vs O(n) for before-context), auto-excludes
node_modules/.git/vendor/etc in recursive scans, iterative BFS-based directory traversal.
find [PATH...] [OPTIONS]
| Flag | Description |
|---|---|
-name PATTERN |
Match filename (case-sensitive glob) |
-iname PATTERN |
Match filename (case-insensitive glob) |
-type TYPE |
Filter by type (f = file, d = directory) |
-empty |
Match empty files/directories |
-maxdepth N |
Descend at most N levels |
-delete |
Delete matched files |
-o, -or |
OR operator between filter groups |
Supports combining multiple filters with -o (OR logic). Glob patterns use * and ?.
Performance: Regex patterns are pre-compiled once at startup, not per-file.
sort [OPTIONS] [FILE...]
| Flag | Description |
|---|---|
-r, --reverse |
Reverse sort order |
-n, --numeric-sort |
Compare by numerical value |
-u, --unique |
Output only unique lines |
uniq [OPTIONS] [INPUT [OUTPUT]]
| Flag | Description |
|---|---|
-c, --count |
Prefix lines by occurrence count |
-d, --repeated |
Only print duplicate lines |
-u, --unique |
Only print unique lines |
-i, --ignore-case |
Case-insensitive comparison |
cp [OPTIONS] SOURCE... DEST
| Flag | Description |
|---|---|
-r, -R, --recursive |
Copy directories recursively |
-f, --force |
Force overwrite |
-i, --interactive |
Prompt before overwrite |
-n, --no-clobber |
Do not overwrite existing files |
-v, --verbose |
Explain what is being done |
mv [OPTIONS] SOURCE... DEST
| Flag | Description |
|---|---|
-f, --force |
Do not prompt before overwriting |
-i, --interactive |
Prompt before overwrite |
-n, --no-clobber |
Do not overwrite existing files |
-v, --verbose |
Explain what is being done |
rm [OPTIONS] FILE...
| Flag | Description |
|---|---|
-r, -R, --recursive |
Remove directories recursively |
-f, --force |
Ignore nonexistent files, never prompt |
-i, --interactive |
Prompt before every removal |
-v, --verbose |
Explain what is being done |
-d, --dir |
Remove empty directories |
mkdir [OPTIONS] DIRECTORY...
| Flag | Description |
|---|---|
-p, --parents |
Create parent directories as needed |
-v, --verbose |
Print message for each created directory |
touch [OPTIONS] FILE...
| Flag | Description |
|---|---|
-c, --no-create |
Do not create any files |
-a |
Change only the access time |
-m |
Change only the modification time |
xargs [OPTIONS] [COMMAND [ARGS...]]
| Flag | Description |
|---|---|
-0, --null |
Input items separated by NUL (for find -print0) |
-I REPLACE |
Replace REPLACE in args with each input item |
-n MAX |
Use at most MAX arguments per command |
-t, --verbose |
Print commands before execution |
-r, --no-run-if-empty |
Don't run command if stdin is empty |
Examples:
find . -name "*.txt" | xargs grep "TODO"
find . -print0 | xargs -0 wc -l
echo file1 file2 | xargs -I {} cp {} /backup/
ls *.log | xargs -n 2 echo "Batch:"For any flag that is not yet implemented, the tools return a standardized error message:
TODO (UNIX WINDOWS): THIS ARGUMENT HAS NOT YET BEEN IMPLEMENTED.
USE AN ALTERNATIVE METHOD, AS THE "ls" COMMAND DOES NOT YET HAVE THIS ARGUMENT "-la".
This message is designed for AI agents to understand and use alternative approaches.
Each tool has integration tests in its tests/ directory:
# Run tests for a specific tool
cd executables\exe_grep
v test tests/
# Run all tests
Get-ChildItem -Directory exe_* | ForEach-Object {
Write-Host "Testing $($_.Name)..."
Push-Location $_.FullName
v test tests/
Pop-Location
}Tests use os.execute() to run the compiled binary and verify exit codes and output. New features and optimizations require new tests — see AGENTS.md for the full testing policy.
executables/
├── AGENTS.MD # Agent-facing documentation & testing policy
├── README.md # This file
├── README.pt-br.md # Brazilian Portuguese version
├── build.ps1 # Build all tools
├── build.bat # Wrapper for build.ps1
├── exe_ls/ # Each tool in its own directory
│ ├── main.v # Entry point & argument parsing
│ ├── lister.v # Core logic (directory listing)
│ ├── filedata.v # Data structures
│ ├── options.v # Options struct
│ ├── utils.v # Utility functions
│ ├── build.bat # Individual build script
│ └── tests/
│ └── ls_test.v # Integration tests
├── exe_grep/
│ ├── main.v
│ ├── matcher.v # Regex/fixed-string matching engine
│ ├── processor.v # File processing & output
│ ├── filters.v # --exclude/--include handling
│ ├── options.v
│ └── tests/
│ ├── grep_test.v
│ ├── context_test.v
│ ├── exclude_test.v
│ ├── literal_test.v
│ └── autoexclude_test.v
└── ... # 14 more tools following the same pattern
- Directory naming:
exe_<command>(e.g.,exe_ls,exe_grep) - Build output: Each
build.batcompiles to../../<command>.exe(thebin/root) - Build flags: All builds use
-prodfor optimized release binaries - Module: All files use
module main - Options: Parsed with V's
flagmodule, stored in anOptionsstruct
cd executables\exe_ls
v -prod -o "..\..\ls.exe" .cd executables
.\build.ps1cd executables\exe_ls
v -o "..\..\ls.exe" .To get the most out of these tools with rtk, use the agent system prompt provided in AGENTS_SUGGESTION_FOR_RTK.md. It enforces:
- MANDATORY use of
rtkwrappers for CLI operations on Windows - FORBIDDEN use of native PowerShell cmdlets (
Select-String,Get-Content,Get-ChildItem) for file/text operations - Short UNIX-style pipelines with
rtk grep ... | rtk head ... - Targeted paths/extensions over broad recursive scans from
. findd | xargs grepto narrow by directory and file type before runninggrep- Auto-exclusion of binary files,
node_modules,.git,build/,dist/, etc. - Auto-exclusion of binary extensions:
*.exe,*.dll,*.sqlite,*.png,*.pdf,*.zip, etc.
See the file for the full ready-to-copy prompt and examples.
Why this matters: PowerShell cmdlets produce verbose, object-formatted output that wastes thousands of AI tokens per call. These UNIX-style tools output dense plain text — a single
rtk grep ... | rtk head -n 80can replace a 200-line PowerShell output with 3-5 lines the LLM can consume instantly.
Internal tooling — part of the rtk ecosystem.