>_EXECUTIVE SUMMARY
Large-scale C-to-Rust port of upstream zsh: strict-port code under src/ported/ plus non-port extensions. The core file table below is regenerated from the same indexer as port_report.html (regex C top-level defs + Rust fn names + port-doc mining). Those counts are a mechanical index, not proof that every path is behavior-complete.
Codebase split (NEW): the runtime crate now physically isolates ported code from non-port code so drift is mechanically detectable.
src/ported/ (107 files) is the strict-port directory — every .rs mirrors a real src/zsh/Src/<x>.c file, every top-level fn carries a /// Port of <cname>() from Src/<file>.c:NNNN doc-comment, and the file set is FROZEN (no new files; PORT.md §"ABSOLUTE FREEZE").
src/extensions/ (40 files) is the non-port directory — features zsh C does not have (AOT, daemon coordination, plugin/script/autoload caches, fish-style autosuggest/abbrev/highlight, persistent worker pools, ZWC byte-code helpers).
src/recorder/ (1 file) is feature-gated; deleted by rustc in the default build.
Both invariants are enforced by tests/port_purity.rs — a regression of either rule fails CI.
Scope note: this report covers the C-to-Rust port (i.e. src/ported/ only) — what was translated from upstream zsh.
It does not cover the new Rust infrastructure layered on top
(zshrs-daemon singleton, zshrs-recorder AOP intercept, IPC + HTTP + OpenAPI surface,
canonical-state rkyv shards, the z* builtin family, session-persistent supervised jobs with
bidirectional ptmx attach, the parser surface in src/ported/parse.rs). That work has no C ancestor and is reported separately in
daemon-report.html. See “BEYOND THE C PORT” section
below for the cross-link.
#[test] Hookspub fn (rg)Overall Line Coverage
Rust line count covers the entire 3-crate workspace (zshrs runtime, compsys, zshrs-daemon) plus fish/, tests/, bins/, and root build.rs. C-line ratio is ~258% Rust : C by raw lines, but most files are more concise than their C source — the inflation comes from the non-port surface (extensions, daemon, fish, compsys) that has no C ancestor. exec.rs alone is 353% of exec.c because it includes 180+ builtins (23 coreutils anti-fork) that C splits across builtin.c.
#FILE-BY-FILE COVERAGE
Per-file columns: C Fns = symbols whose primary C definition is that file (unique name, heuristic indexer). Same-name Rust fn = a Rust definition with the identical identifier. Other rows = the remainder (doc-only pointers, different Rust names, or not yet indexed). Port-index % = ported / total from gen_port_report.py (ported = any Rust hit or port-doc mention). Rust targets: src/ported/<stem>.rs except exec.c → src/exec.rs.
| C Source | Rust Target | C Lines | Rust Lines | Ratio | C Fns | Same-name Rust fn | Other rows | Port-index % | |
|---|---|---|---|---|---|---|---|---|---|
| lex.c | ported/lex.rs | 2,294 | 5,201 | 226.7% | 25 | 25 | 0 | ✅ | |
| parse.c | ported/parse.rs | 4,066 | 9,442 | 232.2% | 75 | 75 | 0 | ⚠️ | |
| subst.c | src/ported/subst.rs | 4,922 | 13,161 | 267.4% | 24 | 24 | 0 | ✅ | |
| math.c | src/ported/math.rs | 1,677 | 5,174 | 308.5% | 20 | 20 | 0 | ✅ | |
| exec.c | src/exec.rs (re-exported as crate::ported::exec) | 6,503 | 0 | 0.0% | 74 | 74 | 0 | ⚠️ | |
| params.c | src/ported/params.rs | 6,511 | 13,253 | 203.5% | 180 | 180 | 0 | ⚠️ | |
| pattern.c | src/ported/pattern.rs | 4,375 | 7,280 | 166.4% | 40 | 40 | 0 | ⚠️ | |
| glob.c | src/ported/glob.rs | 3,973 | 7,011 | 176.5% | 52 | 52 | 0 | ⚠️ | |
| jobs.c | src/ported/jobs.rs | 3,293 | 5,254 | 159.6% | 57 | 57 | 0 | ⚠️ | |
| hist.c | src/ported/hist.rs | 3,965 | 6,703 | 169.1% | 76 | 76 | 0 | ⚠️ | |
| utils.c | src/ported/utils.rs | 7,791 | 12,815 | 164.5% | 172 | 172 | 0 | ⚠️ | |
| prompt.c | src/ported/prompt.rs | 2,562 | 3,965 | 154.8% | 32 | 32 | 0 | ⚠️ | |
| init.c | src/ported/init.rs | 1,965 | 1,879 | 95.6% | 23 | 23 | 0 | ⚠️ | |
| signals.c | src/ported/signals.rs | 1,339 | 2,487 | 185.7% | 27 | 27 | 0 | ⚠️ | |
| TOTAL (core) | 55,236 | 93,625 | 169.5% | 877 | 877 | 0 | ℹ️ | ||
&RENAMING PATTERNS
C uses free functions with global state. Rust uses struct methods, enum variants, and pattern matching. Every “renamed” C function maps to a Rust equivalent under an idiomatic name. This section explains the mapping patterns.
params.c → ParamTable
60+ GSU callback pointers (randomgetfn, uidsetfn, ifsgetfn, homegetfn, termsetfn, etc.) become match arms in ParamTable::get_special_value() and handle_special_set(). Internal helpers (getparamnode, assigngetset, scanparamvals, paramvalarr, getvaluearr) become get_param(), set_scalar(), scan_match(). Env functions (zputenv, addenv, mkenvstr, delenv, copyenvstr) use std::env::set_var/remove_var. Nameref (resolve_nameref_rec, setscope, upscope) becomes resolve_nameref_name(). Uniq array (simple_arrayuniq, newuniqtable, arrayuniq) becomes uniq_array().
parse.c → ShellParser + AST
C’s recursive-descent functions (par_for, par_case, par_if, par_while, par_repeat, par_subsh, par_funcdef, par_time, par_dinbrack, par_simple, par_redir, par_wordlist, par_cond*) become parse_for(), parse_case(), parse_if(), etc. Bytecode system (ecadd, ecdel, ecstrcode, bld_eprog, ecgetstr, ecgetlist, ecgetredirs, init_eprog) replaced by typed AST: ShellCommand enum with Simple, Pipeline, Compound, FunctionDef. ZWC dump/load (dump_find_func, bin_zcompile, load_dump_header, write_dump, build_dump, try_dump_file) moves to zwc.rs.
exec.c → ShellExecutor
execlist→execute_list(), execpline→execute_pipeline(), execsimple→execute_simple(), execode→execute_command(). Function: execshfunc/runshfunc→call_function(), execautofn→autoload_function(). Pipes: spawnpipes/getpipe inline in pipeline execution. Fd: fixfds/closemn/closemnodes inline. Plus 180+ builtins (including 23 coreutils anti-fork) not in C’s exec.c.
glob.c → Qualifier enum
15 qualifier test functions (qualdev, qualnlink, qualuid, qualgid, qualisdev, qualisblk, qualischr, qualisdir, qualisfifo, qualislnk, qualisreg, qualissock, qualflags, qualmodeflags, qualnonemptydir) become enum variants + GlobMatch::from_path(). Match internals (igetmatch, matchpat, parsecomplist, parsepat, insert_glob_match) in getmatch(), pattern_match(), GlobEngine::glob().
init.c → init_main()
zsh_main→init_main(). Subsystem inits (init_signals, init_misc, init_bltinmods, init_shout, setupshin) fold into ShellExecutor::new() and init_main(). Stubs (noop_function, noop_function_int, zleentry, fallback_compctlread) not needed. parseopts_insert/printhelp/getmypath/tccap_get_name handled inline.
lex.c → Lexer struct
lexinit/initlextabs→Lexer::new(). lex_context_save/restore→save_state()/restore_state(). checkalias/exalias inline in next_token(). skipcomm→lex_comment(). Raw buffer ops (zshlex_raw_add/back/mark/back_to_mark) unnecessary — Rust String handles buffer ops natively.
math.c → MathEvaluator
lexconstant part of number parser. callmathfunc→call_math_func(). setmathvar→set_variable(). getmathparam→get_variable(). mathevall→evaluate(). checkunary/notzero/getcvar inline in eval loop.
jobs.c builtins
bin_fg→builtin_fg(), bin_kill→builtin_kill(), bin_suspend→builtin_suspend() in exec.rs. C puts builtins in the same file as infrastructure; Rust separates executor from job internals.
subst.c
wcpadwidth/subst_parse_str inline in SubstState methods. All 22 other functions matched by name.
$KEY FEATURES PORTED
params.c — Full Parameter System
All 80+ special params with dynamic get/set:
$?,$$,$!,$#,$*,$@,$0,$_,$-RANDOM(LCG PRNG, seedable),SECONDS(int + float modes)ERRNO,UID/EUID/GID/EGID(with setuid on assign)COLUMNS/LINES(ioctl),SHLVL,FUNCNEST,OPTIND/OPTARGIFS,HOME,TERM,WORDCHARS,HISTCHARSPS1-PS4,RPS1/2,RPROMPT/2,SPROMPT,POSTEDITPATH/path,CDPATH/cdpath,FPATH/fpathtied pairspipestatus,argv,HISTSIZE/SAVEHIST- Namerefs with loop detection, scope push/pop with save/restore
typeset -pre-executable output,+=augmented assignment
pattern.c — Complete Pattern Engine
Bytecode-compiled pattern matcher:
- Wildcards:
*,?,[...],[!...],[^...] - Extended glob:
#(0+),##(1+),^(negation),~(exclusion) - KSH globs:
?(pat),*(pat),+(pat),!(pat),@(pat) - Numeric ranges:
<n-m>,<n->,<-m> - Backreferences with
()capture groups (9 max) - Case-insensitive:
(#i), lowercase-match-upper:(#l) - POSIX classes:
[:alpha:],[:digit:],[:space:], etc. - Glob flags:
(#b)backrefs,(#m)match refs,(#s)/(#e)anchors - Pattern scope management for completion system
exec.c — 180+ Builtins
Every zsh builtin + 23 coreutils anti-fork:
- Variables:
typeset/local/declare/export/readonly/integer/float - I/O:
print/printf/echo/read/getln/pushln - History:
fc/history/r - Control:
eval/source/exec/command/builtin/noglob - Jobs:
bg/fg/jobs/kill/wait/disown/suspend - Dir:
cd/pushd/popd/dirs/pwd - Options:
set/setopt/unsetopt/emulate - Traps:
trap/kill - Completion:
compgen/complete/compdef/compadd/compset - ZLE:
bindkey/zle/vared - Modules:
zmodload/autoload/functions - Files:
mkdir/rmdir/rm/cp/mv/ln/chmod/chown - Coreutils (anti-fork):
cat/head/tail/wc/sort/find/uniq/cut/tr/seq/rev/tee/sleep/date/mktemp/hostname/uname/whoami/id/basename/dirname/touch/realpath - Misc:
getopts/zparseopts/zstyle/sched/zformat/coproc
glob.c — Full Globbing
Complete file globbing engine:
- Recursive scanning with
**/support - Brace expansion:
{a,b,c},{1..10},{a..z} - 20+ glob qualifiers:
(.)regular,(/)dir,(@)symlink,(=)socket,(p)fifo,(%b)block,(%c)char - Permission qualifiers:
(r)/(w)/(x),(R)/(W)/(X),(s)setuid - Ownership:
(u:name:),(U)owned by EUID - Size/time/links:
(L+n),(m-n),(l+n) - Sorting:
(on)name,(oL)size,(om)mtime - Match/replace:
${var/pat/repl},${var//pat/repl} - Tokenization:
tokenize(),shtokenize(),zshtokenize()
hist.c — Full History
Complete history expansion and management:
- Event designators:
!!,!n,!-n,!string,!?string? - Word designators:
!:0,!:^,!:$,!:*,!:n-m - Quick substitution:
^old^new - Modifiers:
:hhead,:ttail,:rroot,:eext,:l/:ucase,:s/o/n/subst,:&repeat,:q/:Qquote,:xwords,:aabs path - File I/O with locking, extended format timestamps
- Deduplication, blank reduction, word splitting
- History stack for nested parsing contexts
- Search: prefix (
hcomsearch) and substring (hconsearch)
jobs.c — Full Job Control
Complete job lifecycle management:
- Job table with add/remove/reap/expand/shrink
- Process tracking:
update_process,update_job,update_bg_job - Wait:
waitforpid,waitjob,waitjobs,waitonejob - Control:
fg_job,bg_job,disown_job,killjob - Process groups:
acquire_pgrp,release_pgrp - Pipestats tracking with
PIPEFAILsupport - Background status:
addbgstatus/getbgstatus - Superjob/subjob hierarchy
- Time reporting:
format_timewith%E/%U/%S/%P/%J - Signal name/number conversion: all 31 standard signals
utils.c — utility surface
Complete utility library:
- Error/warning:
zerr,zerrnam,zwarn,zerrmsg - Quoting:
quotestring(7 modes),quotedzputs,dquotedztrdup - String ops:
sepsplit,spacesplit,sepjoin,zjoin,colonsplit - Path ops:
expand_tilde,findpwd,lchdir,xsymlink,slashsplit - Named dirs:
finddir,adduserdir,getnameddir,substnamedir - Terminal:
get_term_width/height,adjustwinsize,gettyinfo/settyinfo - Fd:
movefd,redup,zclose,read_loop/write_loop - Escape parsing:
getkeystring(\n\t\xNN\uNNNN\UNNNNNNNN\0NNN\cX) - Spelling correction:
spdist,spckword,spname,mindist - Time:
ztrftime,monotonic_time_ns,zsleep
prompt.c + signals.c + init.c
Complete prompt, signal, and init systems:
- All
%escapes: dir (%~/%//%c), user (%n/%m/%M), status (%?/%#), time (%D/%T/%*), history (%h), jobs (%j), psvar (%v) - Formatting:
%B/%U/%Sbold/underline/standout,%F{color}/%K{color} - Conditionals:
%(?.true.false), truncation, right prompt - True color detection, named colors, highlight parsing
- 28 signal handlers: block/unblock, queue, trap scope management
- Startup sequence:
zshenv,zprofile,zshrc,zlogin,zlogout - Emulation modes: zsh, sh, ksh, csh
@PER-SYMBOL PORT INDEX
Hand-maintained per-function tables previously claimed a fixed “859” row total and drifted (wrong Rust paths, inflated coverage). Those rows are removed. The port_report.html file produced by python3 scripts/gen_port_report.py lists every C symbol the indexer extracts from src/zsh/Src/**/*.c (heuristic: top-level ident( with a following {) together with Rust placement and port-doc pointers — regenerate after upstream or port changes.
The core file table above (between PORT_REPORT:CORETABLE markers) is rewritten by the same script from live tree counts; it is not manually curated.
!TEST RESULTS
Pass/fail counts are intentionally not pinned in this HTML snapshot (they drift with feature flags and cargo version). The static surface is the #[test] hook total in the engineering overview below. For a local matrix run cargo test with the same features you ship; when triaging ordering-sensitive cases, --test-threads=1 remains the tie-breaker.
~ARCHITECTURE: WHY RUST IS DIFFERENT
C wordcode vs Rust AST port
C zsh lowers shell to wordcode (ecadd, ecstrcode, bld_eprog) executed from Src/exec.c. The zshrs parser port surfaces a typed AST instead (ShellCommand::Pipeline(Vec<ShellCommand>, bool), etc.), so many wordcode helpers disappear behind enum variants and structured lowering.
Methods Instead of Function Pointers
C’s parameter system uses GSU (get/set/unset) function pointer structs — 60+ callback functions like randomgetfn, uidsetfn, ifsgetfn. Rust dispatches by parameter name in two central match expressions: get_special_value() and handle_special_set(). Same functionality, ~130 fewer function definitions.
Native UTF-8 vs Meta Encoding
C’s zsh uses a custom “meta” encoding for strings containing special characters (20+ functions: metafy, unmetafy, metalen, unmeta, metacharinc, mb_metacharlenconv, etc.). Rust’s String is natively UTF-8. Most meta functions become identity operations or char iteration.
RAII vs Manual Memory
C requires explicit freearray(), freeparamnode(), freeeprog(), freerepldata(), freestr(), deleteparamtable(). Rust’s ownership system handles all of these automatically via Drop. These functions are provided as no-ops for API completeness.
%ENGINEERING OVERVIEW
Workspace-wide cargo workspace metrics (three packages: zshrs, compsys, zshrs-daemon). Counts below are from wc / rg on 2026-05-23; per-subsystem module tables follow unchanged.
.rs Files#[test] Hookspub fn (tracked .rs)pub structpub enumΔMAY 2026 — RECENT PORT WORK
Three themes closed out across May 2026: (1) every // Deferred / // FAKE / // stub marker in builtin.rs turned into a real C-faithful body, (2) the try_with_executor dispatch path — a Rust-only abstraction that bypassed paramtab — was eliminated entirely from src/ported/ (40 → 0 call sites; only two historical comments remain in subst.rs), and (3) all 30 module files (clone/cap/example/datetime/socket/tcp/stat/zftp/zprof/zselect/watch/zpty/termcap/terminfo/attr/system/zutil/ksh93/db_gdbm/pcre/param_private/mathfunc/langinfo/hlgroup/mapfile/parameter/nearcolor/random/regex/files) were migrated from per-module featuresarray/handlefeatures/getfeatureenables/setfeatureenables stub copies to the canonical crate::ported::module::* impls — 4 stubs × 30 modules = 120 duplicate fake fns deleted, replaced with slice-based module::Features { bn_list, cd_list, mf_list, pd_list } arrays populated with the real BUILTIN/CONDDEF/MATHFUNC/PARAMDEF entries.
Other major de-faking in May: fake structs in hashtable.rs deleted (CmdName / Alias / Reswd / DirCache / SuffixAliasTable / ReswdToken / ShFunc impl block — all replaced with canonical lowercase C-named structs from zsh_h.rs), jobs.rs deleted (JobEntry / BgStatus / PipeStats / CommandTimer / JobPointers fake aggregates; JobState/JobInfo/JobTable moved out to exec_jobs.rs), input.rs deleted (StringInput convenience wrapper, InputBuffer aggregate, INP_* drift constants), glob.rs deleted (GlobOptions / GlobSort / SortOrder / SortSpec / TimeUnit / SizeUnit / RangeOp / impl GlobMatch), cond.rs deleted (CondType / CondResult / CondEval fake enums), module.rs deleted (Wrapper struct + addwrapper/deletewrapper), options.rs deleted (ShellOption enum, with opt_state_get("name") globally swapped to isset(OPT_CONST)).
| Area | What landed | C source | Rust location |
|---|---|---|---|
| builtin.rs | loadautofn — real $fpath walk + file read + PM_UNDEFINED clear (was return-0 stub) | exec.c:5050 | ported/builtin.rs:883 |
| builtin.rs | bin_functions -c autoload-trampoline now invokes loadautofn | builtin.c:3414 | ported/builtin.rs:1593 |
| builtin.rs | scanmatchshfunc wired (replaces stale “funcs.rs” comment that referenced a non-existent file) | builtin.c:3682 | ported/hashtable.rs |
| builtin.rs | bin_functions -M / +M / -m+M — full add/list/remove/match paths into the new MATHFUNCS global | builtin.c:3478–3611 | ported/module.rs:31 |
| builtin.rs | bin_return POSIX-trap promotion to TRAP_STATE_FORCE_RETURN | builtin.c:5845–5854 | exec.rs::TRAP_STATE/TRAP_RETURN |
| builtin.rs | bin_enable toggles for Builtin / Shfunc / Reswd via real disable/enable; new BUILTINS_DISABLED set | builtin.c:541–547 | ported/builtin.rs |
| builtin.rs | init_builtins — real reswdtab.disable("repeat") when not EMULATE_ZSH | builtin.c:212 | ported/builtin.rs:361 |
| signals.rs | SIGPIPE / SIGHUP / SIGINT / SIGWINCH / SIGALRM real bodies (zexit, errflag, stopmsg, adjustwinsize, TMOUT) | signals.c:429–498 | ported/signals.rs:670 |
| signals.rs | POSIXTRAPS option lookup for SIGEXIT sticky-tag bypass | signals.c:746 | ported/signals.rs |
| jobs.rs | kill %jobspec dispatch: real getjob + killjb + SIGCONT-after-stop loop | jobs.c:2989–3010 | ported/jobs.rs:2635 |
| params.rs | getsparam/getiparam/getnparam rewritten to C-faithful single-arg paramtab read (was a drift wrapper around HashMap) | params.c:3076 | ported/params.rs:1726 |
| params.rs | numeric-prefix detection (blanks / minus / 0x / base#) for PM_RIGHT_Z padding | params.c:2446–2466 | ported/params.rs:975 |
| params.rs | fetchvalue real bracket-subscript dispatch into getindex + KSHARRAYS implicit [0] | params.c:2289–2296 | ported/params.rs |
| params.rs | new DELUNSET atomic file-global; deleteparamtable save/restore; freeparamnode unsetfn dispatch | params.c:610 / 5986 | ported/params.rs |
| module.rs | new HOOKTAB global (mirror of Hookdef hooktab) + addhookfunc/deletehookfunc wrappers | module.c:843 | ported/module.rs |
| module.rs | new MATHFUNCS global — user math fn chain for functions -M | module.c:1258 | ported/module.rs:31 |
| zle/zle_main.rs | new WATCH_FDS global — bin_zle -F registration store | zle_main.c:204 | ported/zle/zle_main.rs |
| zle/zle_refresh.rs | new TCOUT_FUNC_NAME global — bin_zle -T tc redisplay transform | zle_refresh.c:246 | ported/zle/zle_refresh.rs |
| zle/zle_vi.rs | VIRANGEFLAG / WORDFLAG / VILINERANGE / VICHGFLAG / VIINREPEAT / VIINSBEGIN atomic file-globals (replaces ViState aggregate) | zle_vi.c:36–78 | ported/zle/zle_vi.rs |
| prompt.rs | sync_from_executor → sync_from_globals: reads paramtab / LASTVAL / curhist / JOBTAB / scriptname directly | prompt.c:56 | ported/prompt.rs |
| utils.rs | printprompt4 reads isset(XTRACE) + getsparam("PS4") + opt_state save/restore | utils.c:1720–1730 | ported/utils.rs:5025 |
| utils.rs | callhookfunc walks shfunctab + paramtab <name>_functions array | utils.c:1494–1514 | ported/utils.rs |
try_with_executor migration: complete. 0 call sites remain in src/ported/ (down from 40). The two surviving mentions are documentation comments in subst.rs:169 and subst.rs:496 referencing the historical removal — no live dispatch path through the fake-executor abstraction.
*MODULE BREAKDOWN BY SUBSYSTEM
| Subsystem | Modules | Lines | % | Coverage Bar | Description |
|---|---|---|---|---|---|
| Core Engine | lexer, parser, exec, subst_port, subst | 29,933 | 23.4% | Lexer, parser (AST), executor (pipelines, redirects, 145 builtins), substitution | |
| ZLE Line Editor | zle/* (28 files) | 35,670 | 27.9% | Keymaps, widgets, vi mode, completion, refresh, history navigation, text objects, complete/complist/compctl/compmatch/compcore | |
| Loadable Modules | datetime, files, stat, system, tcp, pcre, curses, zftp, parameter, ksh93, zutil, ... | 26,418 | 20.7% | 35 module ports: networking, files, PCRE, curses, profiling, pseudo-tty, parameter introspection, math functions, db_gdbm, etc. | |
| Utilities | utils, compat, sort, tokens, input, linklist, mem, ... | 6,204 | 7.3% | String ops, quoting (7 modes), escape parsing, path resolution, spelling correction | |
| Parameters | params, param_private, parameter | 4,596 | 5.4% | 80+ special params, namerefs, scoping, tied pairs, typeset, GSU dispatch | |
| Pattern / Glob | pattern, glob | 4,082 | 4.8% | Compiled pattern engine, glob qualifiers, brace expansion, match/replace | |
| Jobs / Signals | jobs, signals | 2,784 | 3.3% | Process lifecycle, pipestats, trap scopes, signal queuing, fg/bg/disown | |
| Math | math, mathfunc | 2,470 | 2.9% | Arithmetic evaluator, 40+ math functions (sin, cos, rand, int, float, abs, ...) | |
| Prompt / Text | prompt, text | 2,532 | 3.0% | % escape expansion, colors, truncation, right prompt, AST deparsing | |
| History | hist, history | 2,288 | 2.7% | Expansion (!!/!$/^old^new), modifiers (:h:t:r:e:s), file I/O, word splitting | |
| Options / Init | options, init, context | 1,688 | 2.0% | 200+ shell options, startup files, emulation modes (sh/ksh/csh/zsh) | |
| Other | zwc, hashtable, completion, subscript, ... | 3,489 | 4.1% | Compiled scripts (ZWC), hash tables, completion framework, subscript parsing | |
| TOTAL | 208,696 | 100% | |||
+35 LOADABLE MODULE PORTS
Each C module from src/zsh/Src/Modules/ has a corresponding strict-port Rust implementation in src/ported/modules/. Module file set is included in the file freeze on src/ported/; every module now routes its features_ / enables_ / cleanup_ hooks through the canonical module::featuresarray / handlefeatures / setfeatureenables impls instead of per-module Rust-only stub copies.
zsh/attr
zgetattr, zsetattr, zdelattr, zlistattr — extended attributes (xattr)
zsh/cap
cap, getcap, setcap — POSIX capabilities (Linux)
zsh/clone
clone builtin — fork shell to new tty
zsh/curses
zcurses — ncurses windows, colors, attributes, input
zsh/datetime
strftime builtin, $EPOCHSECONDS/$EPOCHREALTIME/$epochtime
zsh/db/gdbm
ztie, zuntie, zgdbmpath — GDBM tied associative arrays
zsh/example
Demonstration module — builtins / conddefs / mathfuncs / paramdefs
zsh/files
chgrp, chmod, chown, ln, mkdir, mv, rm, rmdir, sync + zf_ aliases (18 entries)
zsh/hlgroup
$.zle.esc, $.zle.sgr — highlighting group helper
zsh/ksh93
nameref + .sh.* param family (edchar, edmode, file, lineno, match, name, subscript, subshell, version)
zsh/langinfo
$langinfo — nl_langinfo(3) queries (CODESET, D_FMT, etc.)
zsh/mapfile
$mapfile assoc array — memory-mapped file access
zsh/mathfunc
48 math functions (sin/cos/log/sqrt/atan/copysign/hypot/ilogb/nextafter/scalb/...)
zsh/nearcolor
Hook into get_color_attr for nearest-truecolor remap
zsh/newuser
First-login wizard hook (~/.zshrc seeding)
zsh/param/private
private builtin — local-only param scope override
zsh/parameter
33 magic assoc params: $parameters, $functions, $aliases, $commands, $options, $history, $modules, etc.
zsh/pcre
pcre_compile, pcre_match, pcre_study, =~ condition — Perl-compatible regex
zsh/random
$SRANDOM, zrand_float, zrand_int — /dev/urandom backed
zsh/random/real
Real-valued random number generation (extras for math expressions)
zsh/regex
POSIX regex-match condition — [[ x =~ pat ]]
zsh/net/socket
zsocket builtin — Unix domain sockets
zsh/stat
zstat, stat builtins — stat fields, formatting, array output
zsh/system
syserror, sysread, syswrite, sysopen, sysseek, zsystem flock, systell math fn, $errnos/$sysparams
zsh/net/tcp
ztcp builtin — TCP client/server connections
zsh/termcap
echotc + $termcap assoc — termcap capability database
zsh/terminfo
echoti + $terminfo assoc — terminfo capability database
zsh/watch
log builtin, $WATCH/$watch arrays — login/logout watching, utmp parsing
zsh/zftp
zftp builtin — full FTP client (open / get / put / ls / cd / mkdir / ...)
zsh/zprof
zprof builtin — function profiler (gprof-style call/arc graph)
zsh/zpty
zpty builtin — pseudo-terminal process management
zsh/zselect
zselect builtin — poll/select on file descriptors
zsh/zutil
zformat, zparseopts, zregexparse, zstyle — completion-system utilities
^ZLE LINE EDITOR — 28 FILES, 35,670 LINES
The Zsh Line Editor (ZLE) is a complete terminal-based input system with vi and emacs keybinding modes, programmable widgets, and inline completion. Ported from src/zsh/Src/Zle/*.c. Files mirror the C source 1:1 with the canonical zsh prefix (zle_* / comp* / termquery / deltochar).
| File | Lines | Responsibility |
|---|---|---|
| compctl.rs | 3,170 | Legacy compctl system (pre-compsys, kept for back-compat) |
| compcore.rs | 3,082 | Completion core: shared matcher state, group ordering |
| zle_misc.rs | 2,602 | Miscellaneous widgets: transpose, case change, undo, named-cmd lookup |
| compmatch.rs | 2,179 | Match patterns, anchor matching, case-insensitive matchers |
| zle_main.rs | 2,128 | ZLE main loop, key reading, widget dispatch, initialization, WATCH_FDS |
| zle_keymap.rs | 1,973 | Keymap management, key binding, bindkey builtin |
| computil.rs | 1,831 | Completion utility functions used by _arguments etc. |
| zle_hist.rs | 1,717 | History widgets: up/down, search, accept-line |
| zle_vi.rs | 1,640 | Vi mode: motions, operators, text objects, registers; VIRANGEFLAG / WORDFLAG / VILINERANGE / VICHGFLAG / VIINREPEAT / VIINSBEGIN atomics |
| zle_utils.rs | 1,575 | ZLE utility functions, character classification, prompt expansion |
| zle_refresh.rs | 1,390 | Screen refresh, cursor positioning, line wrapping, TCOUT_FUNC_NAME |
| zle_thingy.rs | 1,349 | Thingy (widget reference) management, zle -A / zle -N |
| zle_move.rs | 1,291 | Cursor movement: word, line, char, matching bracket |
| zle_params.rs | 1,253 | ZLE special parameters: $BUFFER, $CURSOR, $LBUFFER, $RBUFFER, $REGION_ACTIVE, etc. |
| zle_tricky.rs | 1,155 | Completion: prefix matching, menu selection, listing |
| complete.rs | 1,018 | Completion engine: compadd, compset, _arguments dispatch |
| compresult.rs | 982 | Match result presentation, prefix/suffix sharing |
| zle_h.rs | 897 | Header port — keymap / widget / keystruct types |
| zle_word.rs | 854 | Word detection, WORDCHARS handling, shell-word vs vi-word |
| complist.rs | 800 | Menu selection (Tab cycling, arrow nav, mouse) |
| comp_h.rs | 740 | Header port — Cmatcher / Cmgroup / Cmlist types |
| termquery.rs | 627 | Terminal capability queries (tigetstr / tparm) |
| zleparameter.rs | 339 | $widgets, $keymaps, $builtins intro params for zle/parameter module |
| textobjects.rs | 329 | Vi text objects: iw, aw, i", a(, i{, etc. |
| compctl_h.rs | 323 | Header port for compctl |
| zle_bindings.rs | 252 | Default emacs/vi keymap tables |
| deltochar.rs | 119 | Delete-to-char widget (Vi f/t/F/T family) |
| mod.rs | 55 | Module declarations and re-exports |
| TOTAL ZLE | 35,670 |
;145 SHELL BUILTINS
Every zsh builtin is implemented as a builtin_* method on ShellExecutor in exec.rs. This includes all POSIX builtins, all zsh extensions, all loadable module builtins, and file operation builtins.
Variable Declaration (12)
typeset local declare export readonly integer float set unset shift private readarray
I/O (10)
echo print printf read getln pushln sysread syswrite sysopen sysseek
Flow Control (8)
eval source exec command builtin noglob break continue
Job Control (9)
bg fg jobs kill wait disown suspend coproc trap
Directory (6)
cd pushd popd dirs pwd rehash
History (3)
fc history r
Options & Emulation (5)
setopt unsetopt emulate shopt enable
Alias & Function (7)
alias unalias functions autoload unfunction disable hash
Completion (13)
compgen complete compdef compadd compset comptags comptry compopt compinit compctl compcall comparguments compquote
ZLE (4)
bindkey zle vared add-zsh-hook
File Operations (12)
mkdir rmdir rm cp mv ln chmod chown sync zstat zattr zfiles
Lookup (8)
type whence where which unhash caller help let
Modules & Compiled (4)
zmodload zcompile getopts zparseopts
Networking (3)
ztcp zsocket zftp
Terminal & Prompt (5)
echotc echoti ttyctl promptinit prompt
System & Limits (8)
ulimit limit unlimit umask times syserror sysseek exit
Misc (28)
sched zformat zstyle ztie zuntie zgdbmpath strftime zsleep zsystem zselect zpty zprof zregexparse clone log cap zcurses pcre_compile pcre_match pcre_study cdreplay return logout true false test [ :
&DEPENDENCY ARCHITECTURE
┌──────────────────────────────────────┐
│ exec.rs (22,994) │
│ ShellExecutor + 145 builtins │
└──────────┬───────────────────────────┘
│
┌────────────────────┼─────────────────────┐
│ │ │
┌──────▼──────┐ ┌──────▼──────┐ ┌───────▼──────┐
│ parser.rs │ │ lexer.rs │ │ subst_port.rs│
│ (4,099) │ │ (2,551) │ │ (5,021) │
│ AST builder │ │ tokenizer │ │ expansion │
└──────────────┘ └─────────────┘ └──────────────┘
│ │
┌──────────┼──────────────────────────────────────────┤
│ │ │ │ │ │
┌───▼───┐ ┌───▼───┐ ┌───▼───┐ ┌───▼───┐ ┌───▼───┐ ┌───▼────┐
│params │ │pattern│ │ glob │ │ hist │ │ math │ │ text │
│(3,630)│ │(1,581)│ │(2,501)│ │(1,825)│ │(1,714)│ │ (980) │
└───┬───┘ └───────┘ └───────┘ └───┬───┘ └───────┘ └────────┘
│ │
┌───▼───┐ ┌───────┐ ┌───────┐ ┌──▼────┐ ┌────────┐ ┌───────┐
│ utils │ │ jobs │ │signals│ │prompt │ │ init │ │options│
│(3,204)│ │(1,667)│ │(1,117)│ │(1,552)│ │ (598) │ │ (877) │
└───────┘ └───────┘ └───────┘ └───────┘ └────────┘ └───────┘
│
┌──────────┼──────────────────────────┐
│ │ │ │
┌───▼───┐ ┌───▼───┐ ┌───▼───┐ ┌──────▼──────┐
│ zwc │ │ zle/ │ │ cond │ │ 20 modules │
│(1,577)│ │(8,227)│ │ (818)│ │ (16,149) │
└───────┘ └───────┘ └───────┘ └─────────────┘
◆COMPSYS — ZSH COMPLETION SYSTEM IN RUST
A standalone Rust crate reimplementing zsh’s compsys — the programmable completion system. 27 modules, 23,319 lines, 154 public functions. Replaces 24,000+ lines of zsh shell functions with compiled Rust backed by Rkyv caching.
| Module | Lines | Description |
|---|---|---|
| menu.rs | 3,567 | Menu completion: selection UI, scrolling, columns, groups, colors, accept/reject |
| cache.rs | 1,859 | SQLite mirror tables for compsys: autoload paths, compiled function index, invalidation. Mirror only — the authoritative completion cache is the rkyv-mmap'd shard set (zero-copy hot path); this file backs dbview / SQL inspection. |
| functions.rs | 1,244 | Completion function loading, autoload, function resolution from fpath |
| base.rs | 1,177 | Core completion types, match data, completion context, prefix/suffix handling |
| main.rs | 1,077 | Entry point, CLI, completion request dispatching |
| generate.rs | 1,009 | Completion spec generation from command help output, man pages, --help parsing |
| zstyle.rs | 970 | zstyle pattern-based configuration: :completion:* contexts, lookup, inheritance |
| compinit.rs | 831 | Completion system initialization: dump/load, fpath scan, function registration |
| zpwr_colors.rs | 793 | ZPWR color integration: colored completions, syntax highlighting in menu |
| arguments.rs | 767 | _arguments implementation: option specs, argument actions, exclusive groups |
| computil.rs | 675 | Completion utilities: _describe, _values, _alternative, _combination |
| zle.rs | 673 | ZLE integration: widget binding, cursor positioning, buffer manipulation |
| compcore.rs | 640 | Core completion engine: matching, prefix analysis, suffix insertion |
| completion.rs | 635 | Completion result types, display formatting, grouping |
| library.rs | 626 | Completion library management: function registry, lazy loading, caching |
| compset.rs | 616 | compset command: prefix/suffix matching, cursor word extraction |
| state.rs | 495 | Completion state machine: current word, context stack, match state |
| system.rs | 492 | System completions: users, groups, hosts, pids, signals, file types |
| compadd.rs | 458 | compadd builtin: add matches with prefix, suffix, display, description |
| matching.rs | 458 | Match control: case insensitivity, partial matching, anchored/unanchored |
| shell_runner.rs | 399 | Shell function runner: eval completion functions in isolated environment |
| compdef.rs | 305 | compdef command: register completion functions for commands |
| files.rs | 303 | File completion: _path_files, _files, _directories, glob patterns |
| describe.rs | 272 | _describe: completion with descriptions, columnar display |
| lib.rs | 145 | Crate root: public API, re-exports |
| TOTAL COMPSYS | 20,486 | (25 modules in table; bins/menu_demo.rs + bins/bench_autoload.rs add 2,833 for crate total 23,319) |
// 70 COMPLETION FUNCTIONS
Base/Core (35 files)
_wanted, _requested, _dispatch, _setup, _all_labels, _normal, _next_label, _main_complete, _message, _tags, _description, _arguments, _values, _alternative, _describe, _guard, _regex_arguments, _combination, _multi_parts, and more
Base/Utility (30 files)
_path_files, _files, _directories, _users, _groups, _hosts, _pids, _signals, _parameters, _options, _jobs, _command_names, _globquals, _history_complete_word, and more
Unix + Zsh (5 files)
_path_files, _files, _directories (Unix), _command (Zsh) — core file and command completion
⬢FUSEVM + LEX / PARSE (src/ported/)
Runtime bytecode targets the crates.io fusevm crate (pinned in workspace Cargo.toml). Lexing and parsing live in src/ported/lex.rs and src/ported/parse.rs in the runtime crate (the standalone parse package was absorbed back). Stryke / strykelang is a separate repository — it is not part of this workspace; the former Perl-interpreter block here was erroneous pasted content.
// LEX + PARSER (IN-CRATE PORTS)
| File | Lines | Role |
|---|---|---|
src/ported/lex.rs | 4,617 | Lexer port of Src/lex.c — tokens, contexts, alias fusion |
src/ported/parse.rs | 5,015 | Parser port of Src/parse.c — lists, compounds, redirections |
| LEX + PARSE | 9,632 | two files in src/ported/ (no separate parse crate) |
// EXECUTION PIPELINE (ZSHRS)
Source / REPL input (zsh script)
│
▼
┌─────────────────┐ ┌──────────────────┐
│ Lexer │────▶│ Parser │
│ (lex.rs) │ │ (parse.rs) │
│ token stream │ │ AST / commands │
└────────┬────────┘ └────────┬─────────┘
│ │
└───────────┬───────────┘
▼
┌────────────────────┐
│ compile_zsh (+AOT) │ ──▶ fusevm bytecode (workspace crate)
│ extensions/ │
└─────────┬──────────┘
▼
┌────────────────────┐
│ ShellExecutor / VM │ ──▶ builtins, jobs, redirects, zle
└────────────────────┘
●BEYOND THE C PORT — RUNTIME INFRASTRUCTURE
The C-to-Rust port covered above lives under src/ported/ against upstream src/zsh/Src/**/*.c. The numbers below count what zshrs adds — new Rust code with no C ancestor. This is the layer that takes zshrs from “zsh in Rust” to “the first compiled Unix shell with a session-persistent daemon, AOP-intercept recorder, and bidirectional ptmx-attach job supervisor.” Non-port runtime code lives in src/extensions/ — mechanically isolated from src/ported/ by tests/port_purity.rs.
| Crate / Layer | Files | Lines | Pub Fns | Tests | Purpose |
|---|---|---|---|---|---|
src/extensions/ |
34 | 33,474 | 229 | 219 | The non-port directory. Features zsh C demonstrably does not have: AOT compile (aot.rs, compile_zsh.rs), autoload / plugin / script caches (autoload_cache.rs, plugin_cache.rs, script_cache.rs), fish-style features (fish_features.rs), persistent worker pool (worker.rs), arith JIT compiler (arith_compiler.rs), AST s-exp dump (ast_sexp.rs), ZWC byte-code helpers (zwc.rs, zwc_decode.rs), recorder hooks (recorder.rs), daemon presence (daemon_presence.rs), structured logging (log.rs), keymaps / widgets (zle/keymaps.rs, zle/widgets.rs, zle/widget.rs), ext builtins (ext_builtins.rs), regex module (regex_mod.rs), config (config.rs), overlay snapshot + canonical apply (overlay_snapshot.rs, canonical_apply.rs), subscript / fds / hist (subscript.rs, fds.rs, history.rs), stringsort, completion shim. Re-exported at crate root via pub use crate::* aliases so call sites still resolve to crate::aot::*, etc. |
daemon/ |
41 | 23,979 | 202 | 91 | Singleton daemon: IPC server, HTTP listener (auto-derived OpenAPI 3.1), canonical-state engine, fsnotify, schedule, supervisor (jobs + bidirectional ptmx attach), pub/sub bus, named locks, ask-inbox, snapshots, artifacts, cache. Hosts every z* builtin. |
src/recorder/ (feature-gated) |
1 | 1,126 | 46 | 0 | AOP intercept: every state-mutating dispatcher fires a record event with (kind, name, value, file, line, fn_chain). #[cfg(feature = "recorder")]-gated — deleted by rustc in the default zshrs build, compiled into the separate zshrs-recorder binary. Replaces the static-walker approach every other shell uses for completion/fpath scanning. |
fish/ |
157 | 86,917 | 1,244 | 175 | Fish-style reader, syntax highlighter, autosuggestions, abbreviations, env dispatch, history backend, process control, event system. Largest non-port surface in the workspace. |
compsys/ |
27 | 23,319 | 480 | 222 | Completion-system rkyv mmap, read-only SQL mirror, zstyle. Workspace crate; no C ancestor (zsh's compsys is shell-script, not C). |
| NEW INFRASTRUCTURE (rows above) | 260 | 168,815 | 2,201 | 707 | |
Sums cover the five layers in this table only. Workspace-wide Rust LOC (651,206) additionally includes src/ported/, remaining src/ glue, tests/, bins/, and build.rs. | |||||
Architectural moves with no zsh equivalent: the 90/10 daemon/shell work split (singleton daemon owns every mutation; thin shell clients are stateless and forkable);
the recorder-owns-rebuild stance (no in-daemon walker; zshrs-recorder is the sole producer of recorder-managed canonical subsystems);
the single ~/.zshrs/ directory rule (every config + log + sqlite + rkyv shard + socket under one root, configurable via $ZSHRS_HOME);
the z* builtin family (zcache / zls / zsend / znotify / zsubscribe / zjob / zsync / zask / zlock / zpublish / zwhere / zd);
session-persistent supervised jobs with bidirectional ptmx attach (replaces nohup + screen + pueue + disown);
the auto-derived OpenAPI 3.1 surface at GET /openapi from the daemon op registry;
the flat zsh-extended-history text file + sibling FTS5 sqlite index;
zsh grammar introspection to stdout (lexer token stream, Eprog wordcode layout, parser AST S-expression) via zshrs --dump-* and zshrs_dump (dumptokens, dumpwordcode) in formats byte-diffable against parity harnesses — not shipped as a trio by stock zsh.
Full list + governance in
CREATORS.md;
op-by-op detail in
daemon-report.html.
≡GRAND TOTAL — FULL WORKSPACE
Two Rust packages in one Cargo workspace (zshrs + zshrs-daemon; compsys was folded into zshrs). Combined: 651,206 Rust lines (git ls-files '*.rs' | xargs wc -l), 5,483 pub fn lines (git ls-files '*.rs' | xargs rg '^\s*pub fn '), 580 pub struct, 126 pub enum, 14,638 #[test] lines (git ls-files '*.rs' | xargs rg '^\s*#\[test\]') — each rg over the same tracked .rs set as wc, 2026-05-27.
pub fn (rg)#[test] Hooks| Crate | Lines | Files | Pub Fns | Structs | Enums | Tests | Share | Description |
|---|---|---|---|---|---|---|---|---|
zshrs (root, lib zsh) | 416,826 | 354 | 4,975 | 522 | 116 | 5,943 | Runtime: src/ (ported + extensions + exec bridge), fish/, bins/, tests/, build.rs. Lines/tests include integration suites. |
|
compsys | 23,319 | 27 | 480 | 75 | 17 | 222 | Programmable completion: zstyle, compadd, menu selection, SQLite-backed cache. | |
zshrs-daemon | 24,244 | 41 | 202 | 38 | 6 | 91 | Singleton daemon: IPC + HTTP/OpenAPI, canonical shards, jobs, fsnotify, pub/sub. | |
| WORKSPACE | 651,206 | 613 | 5,483 | 580 | 126 | 14,638 |