>_STRYKE REFERENCE
A Perl 5 interpreter written in Rust, optimized for parallelism. NaN-boxed PerlValue, rayon work-stealing across every CPU, bytecode VM with Cranelift JIT, and a pipe-forward (|>) syntax that threads values through chained stages without refs or intermediate vars. This hub links to the authoritative docs in README.md and rustdoc; the sections below give a fast tour of the surface.
Quickstart
Install from crates.io or source, then run scripts or one-liners with s (short for stryke):
# install
cargo install strykelang
# from source
git clone https://github.com/MenkeTechnologies/strykelang
cd strykelang && cargo build --release
# one-liners
s 'p "hello, world"'
s '1:20 |> fi even |> map { _ * _ } |> sum |> p'
s '~>1:20fi{even}map{_*_}sum p'
s 'qw(a b c) |> map uc |> join "," |> p'
s '~> qw(a,b,c) map{uc} join(",") p'
# parallel primitives
s '1:8 |> pmap expensive |> p'
# read + parse JSON
s 'read_json("data.json") |> to_yaml |> p'
s 'p to_yaml read_json "data.json"'
Full install + usage live in the README.
-e is optional. If the first argument isn't a file and looks like code, s runs it directly. s 'p 42' and s -e 'p 42' are equivalent.
Why stryke — One-Liner Comparison
| Feature | stryke | perl5 | ruby | python | awk | jq |
|---|---|---|---|---|---|---|
No -e flag needed | ✓ | ✗ | ✗ | ✗ | — | — |
| No semicolons | ✓ | ✗ | ✓ | ✓ | ✓ | ✓ |
| Built-in HTTP | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ |
| Built-in JSON | ✓ | ✗ | ✗ | ✓ | ✗ | ✓ |
| Built-in CSV | ✓ | ✗ | ✗ | ✓ | ✗ | ✗ |
| Built-in SQLite | ✓ | ✗ | ✗ | ✓ | ✗ | ✗ |
| Parallel map/grep | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ |
Pipe-forward |> | ✓ | ✗ | ✗ | ✗ | ✗ | | |
| Thread macro | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ |
In-place edit -i | parallel | sequential | sequential | ✗ | ✗ | ✗ |
| Data viz (spark/bars/flame) | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ |
| Clipboard | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ |
| JIT compiler | Cranelift | ✗ | YJIT | ✗ | ✗ | ✗ |
| Single binary | 26MB | pkg | pkg | pkg | pkg | 3MB |
Character count — real tasks
| Task | s | perl5 | ruby | python |
|---|---|---|---|---|
| Sum 1:100 | s 'p sum 1:100' 19c | 45c | 28c | 38c |
| Word freq | s -an 'freq(@F) |> dd' 25c | 61c | — | — |
| SHA256 file | s 'p s256"f"' 14c | 70c+ | — | 80c+ |
| CSV → JSON | s 'csv_read("f") |> tj |> p' 33c | needs modules | needs modules | 90c |
| Parallel map | s '1:1e6 |> pmap{_ * 2}' 30c | — | — | — |
Overview
- Parser & compiler — recursive-descent parser in
src/parser.rs, producing an AST consumed by both a tree-walkingInterpreterand a bytecodeCompiler(src/compiler.rs) that feeds the VM (src/vm.rs). Cranelift JIT kicks in for hot blocks and linear subs (src/jit.rs). - Values —
PerlValueis a NaN-boxedu64: immediates (undef,i32, rawf64bits) and taggedArc<HeapObject>pointers for big ints, strings, arrays, hashes, refs, regexes, atomics, channels. - Regex — three-tier engine: Rust
regex→fancy-regex(backrefs) →pcre2(PCRE-only verbs). - Parallelism — every parallel builtin uses rayon work-stealing across all cores. See
pmap,pflat_map,pgrep,pfor,psort,preduce,pcache,ppool,fan,pipeline,par_pipeline_stream,pchannel,pselect,par_walk,par_lines,par_sed. - Binary size — ~21 MB stripped with LTO + O3.
Language reflection
Everything the parser and dispatcher know about is exposed as plain Perl hashes, populated from the source of truth at compile time. build.rs parses category-labeled section comments in is_perl5_core / stryke_extension_name, the try_builtin match arms, and LSP hover docs in doc_for_label_text. Eight hashes — every direct lookup is O(1).
Forward maps
| Long name | Short | Key → Value |
|---|---|---|
%stryke::builtins | %b | primary callable name → category. Clean unique-op count. |
%stryke::all | %all | every spelling (primary + alias) → category. Aliases inherit their primary's tag. Use for scalar keys %all. |
%stryke::perl_compats | %pc | subset of %b: Perl 5 core only, name → category |
%stryke::extensions | %e | subset of %b: stryke-only, name → category |
%stryke::aliases | %a | alias → canonical primary |
%stryke::descriptions | %d | name → LSP one-liner (sparse) |
Inverted indexes (O(1) reverse-query)
| Long name | Short | Key → Value |
|---|---|---|
%stryke::categories | %c | category → arrayref of names ($c{parallel} → [pmap, pgrep, …]) |
%stryke::primaries | %p | primary → arrayref of its aliases ($p{to_json} → [tj]) |
Examples
Notes
- Every
$h{name}lookup is O(1). Inverted indexes (%c,%p) let you do reverse-queries in O(1) too; filters likegrep { cond } keys %hare still O(n). - Hash sigil namespace is separate from scalars/functions — the short-alias letters don't collide with
$a/$bsort specials, theeextension function, or any other stryke name. %descriptionsis sparse:exists $d{$name}doubles as "is this documented in the LSP?".- A value of
"uncategorized"in%builtinsflags a name that's dispatched at runtime but missing a// ── category ──section comment inparser.rs.
Pipe-forward
The |> operator (F# / Elixir) threads a value into the first argument of the next call — parse-time only, zero runtime cost.
x |> f # f(x)
x |> f(a, b) # f(x, a, b)
x |> f |> g(2) # g(f(x), 2)
# real pipeline — count words per file, top 10 longest:
f("*.txt") |> map { [_, slurp(_) |> split(/\s+/) |> scalar] }
|> sort { $b->[1] <=> $a->[1] }
|> take(10)
|> dd
Precedence sits between ?: and ||, so x + 1 |> f || y parses as f(x + 1) || y.
Pipe-RHS sugar
- Thread macro —
t EXPR s1 s2 s3expands toEXPR |> s1 |> s2 |> s3. Stages likepow(_, 2)use bare_(or_) as a placeholder, auto-wrapped in a coderef. Bare_=_in any expression — enablesmap{_*2}fi{_>5}. >{ BLOCK }— IIFE anywhere an expression is valid; also works as a pipe stage (lhs |> >{ body }).@[...]— sugar for@{[...]}(deref anonymous arrayref inline).%[k => v]— sugar for%{+{k => v}}(deref anonymous hashref inline, sidesteps the block-vs-hashref ambiguity).
Builtin categories
3200+ operations across 3700+ spellings. Query them via keys %stryke::builtins — the table below is a navigational overview, not a full index. Run s 'p scalar keys %b' for the live count.
Array / List (134+)
map maps flat_map grep sort reverse push pop shift unshift splice reduce fold fore e first any all none take take_while drop skip_while partition min_by max_by zip zip_with interleave frequencies count_by chunk windowed enumerate shuffle uniq dedup compact flatten concat pluck grep_v with_index sorted sorted_desc sorted_nums without take_last drop_last pairwise batch rotate swap_pairs sliding_pairs run_length_encode group_consecutive permutations combinations power_set cartesian_product …
String (129+)
chomp chop length substr index rindex split join uc lc ucfirst lcfirst chr ord trim lines words chars snake_case camel_case kebab_case pascal_case constant_case capitalize swap_case title_case squish pad_left pad_right center truncate_at reverse_str rot13 rot47 caesar_shift count_vowels count_consonants first_word last_word left_str right_str wrap_text dedent indent strip_html levenshtein soundex extract_numbers extract_emails extract_urls …
Math / Numeric (147+)
abs int sqrt sin cos tan asin acos atan sinh cosh tanh exp log rand srand inc dec avg stddev clamp normalize range even odd zero positive negative sign negate double triple half round floor ceil gcd lcm factorial fibonacci is_prime divisors sieve_primes cbrt log2 log10 hypot rad_to_deg deg_to_rad pow2 softmax argmax argmin …
Conversion / Units (102+)
c_to_f f_to_c c_to_k k_to_c miles_to_km km_to_miles feet_to_m m_to_feet inches_to_cm kg_to_lbs lbs_to_kg bytes_to_kb bytes_to_mb bytes_to_gb seconds_to_minutes hours_to_seconds liters_to_gallons cups_to_ml joules_to_cal watts_to_hp pascals_to_psi to_bin to_hex to_oct from_bin from_hex from_oct to_base from_base …
Validation (91+)
is_empty is_blank is_numeric is_upper is_lower is_alpha is_digit is_alnum is_space is_palindrome is_prime is_sorted is_subset is_superset is_valid_ipv4 is_valid_ipv6 is_valid_email is_valid_url is_valid_json is_valid_semver is_valid_base64 is_ascii is_printable luhn_check is_undef is_defined is_array is_hash is_code is_ref is_int is_float …
Hash / Map (52+)
keys values each delete exists select_keys top invert merge_hash has_key has_any_key has_all_keys pick omit hash_size hash_from_pairs pairs_from_hash hash_eq keys_sorted values_sorted hash_insert hash_update hash_delete zipmap counter
Encoding / Crypto (64+)
sha1 sha256 sha384 sha512 md5 hmac_sha256 uuid crc32 base64_encode base64_decode hex_encode hex_decode url_encode url_decode gzip gunzip zstd zstd_decode jwt_encode jwt_decode html_escape_str html_unescape_str shell_escape sql_escape hex_dump random_password random_hex_str
I/O (62+)
print p say printf open close eof readline read seek tell slurp input capture pager/pg/less binmode flock getc select truncate read_lines append_file to_file read_json write_json tempfile tempdir file_size file_mtime file_atime is_symlink is_readable is_writable is_executable xopen/xo
Filesystem (84+)
files/f fr dirs/d dr sym_links glob glob_par basename dirname realpath which stat lstat size copy move spurt read_bytes path_ext path_stem path_parent path_join path_split path_is_abs path_is_rel strip_prefix strip_suffix ensure_prefix ensure_suffix
Serialization
to_json/tj to_csv/tc to_toml/tt to_yaml/ty to_xml/tx to_html/th to_markdown/to_md/tmd ddump/dd stringify/str json_encode/decode yaml_encode/decode toml_encode/decode xml_encode/decode json_pretty json_minify escape_json
Parallel (31)
pmap pflat_map pgrep pfor psort preduce preduce_init pmap_reduce pmap_chunked pcache ppool pchannel pselect puniq pfirst pany fan fan_cap pipeline par_pipeline_stream glob_par par_walk par_lines par_sed par_find_files par_line_count pwatch watch
Functional (56+)
reduce fold inject collect complement constantly coalesce default_to when_true when_false if_else safe_div safe_mod safe_sqrt safe_log scan accumulate keep_if reject_if group_consecutive normalize_list softmax argmax argmin juxt2 juxt3 tap_val debug_val converge iterate_n unfold …
Matrix / Linear Algebra (29+)
dot_product cross_product matrix_add matrix_scale matrix_multiply identity_matrix zeros_matrix ones_matrix diagonal matrix_trace matrix_shape matrix_row matrix_col magnitude vec_normalize vec_add vec_sub vec_scale linspace arange
Data / Network (50+)
fetch fetch_json fetch_async par_fetch csv_read csv_write dataframe sqlite json_jq ipv4_to_int int_to_ipv4 email_domain email_local url_host url_path url_query url_scheme
Date / Time (48+)
time localtime gmtime is_leap_year days_in_month month_name weekday_name quarter_of now_ms now_us now_ns unix_epoch today yesterday tomorrow is_weekend is_weekday datetime_utc datetime_from_epoch datetime_strftime
System / Process (35+)
system exec exit fork wait waitpid kill alarm sleep os_name os_arch num_cpus pid ppid uid gid username home_dir temp_dir cwd is_root uptime_secs cmd_exists env_get env_has env_set env_keys env_pairs signal_name has_stdin_tty has_stdout_tty
Geometry
distance_2d distance_3d midpoint slope area_triangle area_circle circumference perimeter_rect area_rect point_in_circle point_in_rect
Color / ANSI
rgb_to_hex hex_to_rgb ansi_red ansi_green ansi_blue ansi_yellow ansi_cyan ansi_magenta ansi_bold ansi_dim strip_ansi darken lighten mix_colors is_dark is_light
Random
rand srand coin_flip dice_roll random_int random_float random_bool random_choice random_between random_string random_alpha random_digit random_password random_hex_str
Data Structures
set heap deque stack_new queue_new lru_new counter counter_most_common defaultdict ordered_set bitset_new bitset_set bitset_test bitset_clear
Async / Timing
async spawn await timer bench trace eval_timeout retry rate_limit every gen
Reflection
Eight O(1) hashes — %b builtins, %all every spelling, %pc perl_compats, %e extensions, %a aliases, %d descriptions, %c categories, %p primaries.
Parallel primitives (highlights)
Every p* primitive uses rayon work-stealing, saturates all cores by default, and takes three surface forms:
# block form (_ = element, bare _ is shorthand for _)
pmap { _ * 2 } 1:1_000_000
# expression form
pmap _ * 2, 1:1_000_000
# bare-fn form (fn double { $_0 * 2 })
pmap double, 1:1_000_000
fan / pchannel / ppool
# fan — run a block N times in parallel (_/$_0 = index 0..N-1)
fan 16 { heavy_work(_) }
# pchannel — bounded MPMC queue
my ($tx, $rx) = pchannel(100)
async { $tx->send(_) for 1:1000; undef $tx }
while (defined(my $v = $rx->recv)) { p $v }
# ppool — persistent worker pool
my $pool = ppool 4, fn {
while (defined(my $j = $rx->recv)) { process($j) }
}
$tx->send(_) for @jobs; undef $tx
$pool->join
Pipelines
# sequential (each stage drains list before next)
pipeline(
fn { map { _ * 2 } @_ },
fn { grep { _ > 10 } @_ },
fn { sum(@_) },
)->run(1:1000)
# streaming — bounded crossbeam channels, concurrent stages
par_pipeline_stream([\&stage1, \&stage2, \&stage3], \@input)
Perl-compat highlights
- OOP —
@ISA, C3 MRO (live, not cached),$obj->SUPER::method,tiefor scalars/arrays/hashes withTIESCALAR/TIEARRAY/TIEHASH, plusEXISTS/DELETE;use overloadwith full binary dispatch,nomethod, unaryneg/bool/abs. Nativeclasssyntax with inheritance, traits, abstract/final, visibility, static fields, operator overloading, and reflection — see OOP section below. - Specials —
$?packed POSIX status,$|autoflush,$.line count (undef until first read),@ARGV,%ENV,%SIG(SIGINT/SIGTERM/SIGALRM/SIGCHLD),format/write(partial). - Phases —
BEGIN/UNITCHECK/CHECK/INIT/ENDrun in Perl order;${^GLOBAL_PHASE}matches Perl in both tree-walker and VM. - Interpolation —
$var,#{expr},$h{k},$a[i],@a,@a[slice],$#a,$0,$1..$n;\x{hex}and unbraced\x. - Strict / modules — per-mode
use strict 'refs'etc.,@INCbuilt from-I,vendor/perl, system Perl's@INC, script dir,STRYKE_INC.List::Utilis native Rust.
Full list in the README §0x08.
Object-Oriented Programming
Stryke supports both Perl 5 OOP (bless, @ISA, tie, use overload) and a native class syntax with inheritance, traits, visibility, static fields, operator overloading, and full reflection.
Class basics
Declare classes with typed fields, defaults, and instance methods. Fields get auto-generated getters/setters. $self is implicit in methods.
class Dog {
name: Str
breed: Str = "Mixed"
fn bark { "Woof from " . $self->name }
}
my $d = Dog(name => "Rex") # named construction
my $d = Dog("Rex", "Lab") # positional construction
p $d->name # getter → "Rex"
$d->name("Max") # setter
p $d->bark() # "Woof from Max"
Methods with parameters
class Calculator {
value: Int = 0
fn add($n) { $self->value + $n }
}
my $c = Calculator(value => 10)
p $c->add(5) # 15
Static methods
class Math {
fn Self.add($a, $b) { $a + $b }
fn Self.pi { 3.14159 }
}
p Math::add(3, 4) # 7
p Math::pi() # 3.14159
Inheritance (extends)
Single and multiple inheritance. Parent fields and methods are inherited. C3 MRO for diamond resolution.
class Animal {
name: Str
fn speak { "Animal: " . $self->name }
}
class Dog extends Animal {
fn speak { "Woof from " . $self->name } # override
}
my $d = Dog(name => "Rex")
p $d->speak() # "Woof from Rex"
# multiple inheritance
class A { a: Int = 1 }
class B { b: Int = 2 }
class C extends A, B { c: Int = 3 }
my $c = C()
p $c->a . "," . $c->b . "," . $c->c # "1,2,3"
Abstract classes
Cannot be instantiated directly. Subclasses must implement abstract methods.
abstract class Shape {
name: Str
fn describe { "Shape: " . $self->name }
}
# Shape(name => "x") → ERROR: cannot instantiate abstract class
class Circle extends Shape { radius: Int }
my $c = Circle(name => "ring", radius => 5)
p $c->describe() # "Shape: ring"
Final classes and methods
final class prevents subclassing. final fn prevents method override in subclasses. Both checked at declaration time.
final class Config { value: Int = 42 }
# class Bad extends Config { } → ERROR: cannot extend final class
class Base {
final fn id { 42 }
fn label { "base" } # can be overridden
}
class Child extends Base { }
my $c = Child()
p $c->id() # 42 (inherited, cannot override)
Visibility (pub / prot / priv)
Applies to both fields and methods. Runtime enforcement on access.
class Secret {
pub visible: Int = 1 # public (default)
priv hidden: Int = 42 # own class only
prot internal: Int = 99 # class + subclasses
fn get_hidden { $self->hidden } # internal access ok
}
class Child extends Secret {
fn get_internal { $self->internal } # prot: ok from subclass
}
my $s = Secret()
p $s->get_hidden() # 42
# $s->hidden → ERROR: private field
my $c = Child()
p $c->get_internal() # 99
# $c->internal → ERROR: protected field (outside class hierarchy)
Static fields
Shared across all instances. Access via ClassName::field() (getter) / ClassName::field(value) (setter).
class Tracker {
static total: Int = 0
name: Str
fn BUILD { Tracker::total(Tracker::total() + 1) }
}
my $a = Tracker(name => "a")
my $b = Tracker(name => "b")
p Tracker::total() # 2
BUILD / DESTROY hooks
BUILD runs after field init (parent first, then child). DESTROY runs in reverse (child first, then parent).
class Base {
log: Str = ""
fn BUILD { $self->log("base") }
}
class Child extends Base {
fn BUILD { $self->log($self->log . "+child") }
}
my $c = Child()
p $c->log # "base+child"
# DESTROY — child runs first
class Base {
static log: Str = ""
fn DESTROY { Base::log(Base::log() . "base,") }
}
class Child extends Base {
fn DESTROY { Base::log(Base::log() . "child,") }
}
my $c = Child()
$c->destroy()
p Base::log() # "child,base,"
Traits
Interface contracts with required and default methods. Enforced at class declaration.
trait Loggable {
fn log_prefix { "LOG" } # default (optional to implement)
fn log_msg # required (no body)
}
class Event impl Loggable {
msg: Str
fn log_msg { $self->msg }
}
my $e = Event(msg => "hello")
p $e->log_msg() # "hello"
p $e->does("Loggable") # 1
# Missing required method → compile-time error
# class Bad impl Loggable { } → ERROR: missing required method 'log_msg'
Late static binding (static::)
Resolves to the runtime class of $self, unlike SUPER:: which is compile-time.
class Base {
fn class_name { static::identify() }
fn identify { "Base" }
}
class Child extends Base {
fn identify { "Child" }
}
my $c = Child()
p $c->class_name() # "Child" (not "Base")
Operator overloading
Define op_add, op_sub, op_mul, op_div, op_mod, op_pow, op_eq, op_ne, op_lt, op_gt, op_le, op_ge, op_spaceship, op_neg, op_bool, op_abs, op_concat, stringify, and more.
class Vec2 {
x: Int
y: Int
fn op_add($other) {
Vec2(x => $self->x + $other->x, y => $self->y + $other->y)
}
fn op_neg { Vec2(x => -$self->x, y => -$self->y) }
fn stringify { "(" . $self->x . "," . $self->y . ")" }
}
my $a = Vec2(x => 1, y => 2)
my $b = Vec2(x => 3, y => 4)
my $c = $a + $b
p "$c" # "(4,6)"
my $d = -$a
p "$d" # "(-1,-2)"
Reflection / introspection
class Animal { name: Str; fn speak { "..." }; fn eat { "nom" } }
class Dog extends Animal { breed: Str }
my $d = Dog(name => "Rex", breed => "Lab")
p join(",", $d->fields()) # "name,breed"
p join(",", $d->methods()) # "speak,eat" (inherited)
p join(",", $d->superclass()) # "Animal"
p $d->isa("Dog") # 1
p $d->isa("Animal") # 1 (inherited)
p $d->isa("Cat") # "" (false)
Built-in instance methods
| Method | Description |
|---|---|
$obj->fields() | List of all field names (including inherited) |
$obj->methods() | List of all method names (including inherited) |
$obj->superclass() | List of parent class names |
$obj->isa("Class") | Checks inheritance chain |
$obj->does("Trait") | Checks trait implementation |
$obj->clone() | Deep copy (independent instance) |
$obj->with(k => v) | Functional update — returns new instance with changed fields |
$obj->to_hash() | Convert to hash reference |
$obj->destroy() | Explicit destructor call (triggers DESTROY chain) |
"$obj" | Stringify — Class(field => val, ...) or custom stringify |
Field types
Runtime validation on setter. Float accepts both int and float. Custom types (struct/enum names) also work.
class Typed {
count: Int # integer
name: Str # string
ratio: Float # int or float
items: Array # array reference
map: Hash # hash reference
any_val # untyped (Any)
}
Extensions beyond stock Perl 5
- Native data — CSV (
csv_read/csv_write), columnardataframe, embeddedsqlite, TOML/YAML helpers. - HTTP —
fetch/fetch_json/fetch_async/par_fetch. - Crypto / compression —
sha256,hmac_sha256,jwt_encode/decode,gzip/gunzip/zstd. - Standalone binaries —
s build SCRIPT -o OUTbakes a script into a self-contained executable. - Inline Rust FFI —
rust { pub extern "C" fn ... }blocks compile to a cdylib on first run, dlopen + register as Perl-callable subs. - Bytecode cache —
STRYKE_BC_CACHE=1skips parse + compile on warm starts via on-disk.pecbundles. - Distributed compute —
cluster([...])builds an SSH worker pool;pmap_on $cluster { } @listfans a map across persistent remote workers with fault tolerance. - Shared state —
mysyncdeclares atomic variables safe to mutate from parallel workers. - Language server —
s lsp(ors --lsp) runs an LSP server over stdio with diagnostics, hover, completion. The five reflection hashes above are part of the completion surface.
CLI flags (common)
-e CODE // one-line program (multiple -e's allowed) -E CODE // like -e, but enables all optional features -c // syntax check only --lint / --check // parse + compile bytecode without running --disasm // print bytecode disassembly before VM run --ast // dump parsed AST as JSON and exit --fmt // pretty-print parsed Perl to stdout and exit --profile // wall-clock profile stderr (flamegraph-ready) --flame // flamegraph: terminal bars (TTY) or SVG --no-jit // disable Cranelift JIT (bytecode interpreter only) --compat // Perl 5 strict-compat: disable all stryke extensions -n / -p / -i // stdin line-mode + in-place edit -j N // parallel threads for multi-file execution // Subcommands s build SCRIPT -o OUT // AOT compile to standalone binary s build --project DIR // bundle project (main.stk + lib/) into binary s check FILE... // parse + compile without executing (CI/editor) s disasm FILE // disassemble bytecode s profile FILE // run with profiling (--flame for SVG) s fmt -i FILE... // format source files in place s bench // run benchmarks from bench/ or benches/ s test // run tests from t/ s init NAME // scaffold new project (lib/, bench/, t/) s repl --load FILE // REPL with pre-loaded file s lsp // language server over stdio s completions zsh // emit shell completions s ast FILE // dump AST as JSON s prun FILE... // run multiple files in parallel s convert FILE... // convert Perl to stryke syntax s deconvert FILE... // convert stryke back to Perl s --remote-worker // worker process for distributed cluster
zshrs — The Most Powerful Shell Ever Created
zshrs is a drop-in zsh replacement written in Rust. Full bash/zsh/fish compatibility, SQLite-indexed completions, and native stryke parallel operations.
Why zshrs?
| vs zsh | vs fish | vs bash |
|---|---|---|
| 10x faster startup | Full POSIX compat | Fish-quality UX |
| SQLite history (frequency, duration, exit status) | Runs .bashrc unchanged | Modern completions |
| Native stryke parallel ops | No syntax translation needed | Syntax highlighting |
| ZWC precompiled function support | Global/suffix aliases | Autosuggestions |
Core features
| Feature | Description |
|---|---|
| zsh/bash/fish compat | Runs .zshrc, .bashrc, shell scripts unchanged |
| Fish-style highlighting | Real-time colorization — commands green, strings yellow, errors red, variables cyan |
| Fish-style autosuggestions | Ghost-text completions from history, accept with → |
| Fish-style abbreviations | g → git, gco → git checkout, expand with space |
| SQLite completions | FTS5 prefix search indexes all PATH executables for instant fuzzy completion |
| SQLite history | Frequency-ranked, timestamped, tracks duration and exit status per command |
| Stryke mode | Prefix any line with @ for full parallel primitives |
| ZWC support | Reads compiled .zwc files for fast function loading |
| Job control | Full &, fg, bg, jobs, wait, disown |
| Traps & signals | trap 'cmd' EXIT INT TERM ERR DEBUG |
| Hooks | precmd, preexec, chpwd, add-zsh-hook |
| zsh modules | zpty, zsocket, zprof, sched, zparseopts |
| PCRE regex | pcre_compile, pcre_match with capture groups |
| Shell emulation | emulate zsh, bash, ksh, sh |
Build options
| Build | Size | @ mode | Command |
|---|---|---|---|
| Fat | ~24MB | Yes | cargo build --release (strykelang) |
| Lean | ~4MB | No | cargo build --release -p zsh |
Usage
zshrs # interactive shell
zshrs -c 'echo hello' # execute command
zshrs script.sh # run script file
zshrs --dump-zwc file.zwc # inspect compiled zsh files
# In interactive mode, @ enters stryke (fat build only):
$ @ 1:100 |> sum |> p
5050
$ @ fetch_json("https://api.github.com/users/octocat") |> dd
$ @ ls |> pmap { stat(_)->{size} } |> sum |> p # parallel file sizes
$ @ glob("**/*.rs") |> pgrep { slurp(_) =~ /TODO/ } |> p
Default abbreviations (fish-style)
Abbreviations expand inline when you press space — type gs<space> and it becomes git status .
| Abbr | Expansion | Abbr | Expansion |
|---|---|---|---|
g | git | ga | git add |
gaa | git add --all | gc | git commit |
gcm | git commit -m | gco | git checkout |
gd | git diff | gds | git diff --staged |
gp | git push | gpl | git pull |
gs | git status | gsw | git switch |
gb | git branch | gl | git log --oneline |
cb | cargo build | cr | cargo run |
ct | cargo test | cc | cargo check |
cf | cargo fmt | ccl | cargo clippy |
dc | docker compose | dcu | docker compose up |
k | kubectl | kgp | kubectl get pods |
... | ../.. | .... | ../../.. |
Full feature reference
Parameter expansion
${var:-default}, ${#var}, ${var:offset:len}, ${var#pat}, ${var/old/new}, ${(U)var}, ${(s/:/)var}, ${(o)arr}, ${(k)assoc}
Arrays
arr=(a b c), ${arr[1]}, ${arr[-1]}, ${arr[2,4]}, arr+=(d), declare -A map, map[k]=v
Control flow
if/elif/else/fi, for/do/done, for ((;;)), while/until, case/esac, select, repeat N cmd, {} always {}
Arithmetic
$((expr)), ((stmt)), let, + - * / % **, & | ^ ~ << >>, ++ --, ?: ,, hex/octal/binary literals
Conditionals
[[ ]], [ ], -eq -ne -lt -gt, == != < >, -z -n, =~ regex, -e -f -d -L -r -w -x -s -nt -ot
Redirection
> >> < 2> &>, 2>&1, >| force, heredoc <<EOF, herestring <<<, process sub <(cmd) >(cmd)
Globbing
* ? [abc] [!a] [a-z], {a,b,c}, {1..10}, {0..10..2}, **/*.rs, qualifiers *(.) *(/) *(@) *(om)
Functions
f() {}, function f {}, local, return, $@ $* $#, autoload -Uz, functions, unfunction
Aliases
alias, unalias, global alias -g G='|grep', suffix alias -s txt=cat
Job control
&, jobs, fg, bg, wait, disown, suspend, kill, %1 %+ %- %?str
Traps
trap 'cmd' EXIT INT TERM ERR DEBUG CHLD, trap - reset, trap '' ignore, kill -l
History
history, fc, !!, !-2, !42, !echo, !?pat, !$ !^ !*, ^old^new
Prompt
%n %m %~ %? %j %T %D, \u \h \w \W \$, RPROMPT, colors %F{red} %f
Hooks
precmd, preexec, chpwd, periodic, add-zsh-hook
zsh modules
zpty, zsocket, zprof, sched, zformat, zparseopts, zregexparse, pcre_compile/match, zstyle, zstat
Options
setopt/unsetopt: autocd, extendedglob, nullglob, pipefail, noclobber, histignorespace, sharehistory
See the full zshrs documentation in README for complete reference with examples.
Repository & links
- Source — github.com/MenkeTechnologies/stryke
- Crate — crates.io/crates/stryke (
cargo install strykelang) - Rust API docs — docs.rs/stryke
- Issues — github.com/MenkeTechnologies/stryke/issues
- Full README — README on GitHub (install, parallel primitives, mysync, CLI flags, architecture, benchmarks, standalone binaries, inline Rust, bytecode cache, distributed
pmap_on, LSP). - Parity —
parity/cases/*.plholds 20k+ Perl-vs-s test cases run byparity/run_parity.sh.