A zsh-compatible shell with BrightDate woven natively into its builtins, parameters, prompt escapes, and file timestamps. One sortable, timezone-free scalar — everywhere.
Shell scripts that touch time pay a hidden tax: parsing
date output, juggling $TZ, sub-shelling out
to gdate on macOS, fighting epoch formats that differ
between stat on Linux vs BSD, and re-implementing
duration math by hand. BSH replaces all of that with a single decimal
scalar — a timezone-free Float64 count of SI days since J2000.0 (the
same epoch used by every space agency and observatory).
BSH is the living proof: every time-related surface in the
shell — prompt, ls -l, stat,
history -d, sched, times —
emits the same float. No translation. No format mismatch. Duration
arithmetic in $(( )) just works.
The BSH chsh challenge:
switch your login shell for a week. Your prompt shows the BrightDate.
Your files are stamped in BrightDate. Your history is indexed in
BrightDate. Duration arithmetic happens in your head. Once you stop
translating, it's hard to go back — that's the point.
BrightDate is a
Float64 count of SI days since the astronomical epoch
J2000.0,
computed on a TAI substrate. Trivially sortable, diffable, and
storable — b − a = elapsed days, no exceptions.
| Problem | BrightDate fix |
|---|---|
| Timezone soup | Single universal value, no zones |
| Leap-second stutters | TAI substrate — monotonic, no jumps |
| Duration arithmetic | b - a in shell $(( … )) |
| Sorting timestamps |
Float compare; works in sort -n,
awk, jq
|
| 2038 / Y10K | ±287,000 years at sub-µs in current era |
date portability |
Identical output on macOS, Linux, BSD, WSL |
BSH = zsh 5.10 + a statically-linked Rust core (brightdate-rust) wired into the shell's C internals through a single FFI entry
point:
double bsh_unix_to_brightdate(double unix_secs);
double bsh_brightdate_to_unix(double bd);
From those two anchors, every time-related surface — builtins,
parameters, prompt escapes, history, file timestamps — speaks
BrightDate. Nothing parses strings. Nothing re-derives the epoch.
The number that comes out of $BRIGHTEPOCH is the same
number that stat prints for mtime, the
same number in your prompt, and the same number you can subtract
in an arithmetic expansion.
BSH stays 100% zsh-compatible: every traditional builtin, option, and module still works. BrightDate is layered on top — you opt in by loading the modules you want.
BSH bakes BrightDate directly into the classic Unix date/time
commands. date, time, uptime,
cal, and watch are shell builtins that emit
BrightDate values — no fork, no external process, no
$TZ dance. The traditional binaries are shadowed
transparently, so existing scripts switch over for free.
dateCurrent date as BrightDate (replaces system
date)
timeCurrent time of day in BrightDate units (replaces system
time)
uptimeSystem uptime in
millidays — 1
md = 86.4 s (replaces system uptime)
calCalendar in BrightDate notation (replaces system
cal)
watchWatch a command; elapsed time reported in millidays (replaces
system watch)
$BRIGHTEPOCH
From bsh/datetime. Read-only Float64 parameter
holding the current BrightDate, updated on every access — the
analogue of $EPOCHREALTIME. Perfect for elapsed-time
arithmetic in scripts.
start=$BRIGHTEPOCH
do_work
echo "elapsed: $(( BRIGHTEPOCH - start )) md"
%P
In any PROMPT, RPROMPT, or
PS4, %P expands to the current
BrightDate (6 d.p.).
%B is already bold, so BrightDate claims P for "Present."
PROMPT='[%P] %# '
# renders as:
# [9622.841738] %
history -d / fc -D
With EXTENDED_HISTORY set,
history -d (or -i, -f,
-E) prints command-execution timestamps as BrightDate
values instead of clock strings. fc -l -D reports
command durations in millidays instead of seconds
— so log analysis just becomes sort -n.
ls -l, stat
From bsh/files and bsh/stat.
bsh/stat is statically linked and autoloaded — no
zmodload required; bsh/files ships as a
dynamic module (zmodload bsh/files).
ls -l replaces the timestamp column with a BrightDate
decimal, following normal ls flags (-u for atime,
-c for ctime, etc.). The stat builtin
emits all time fields — atime, mtime,
ctime, and the new btime (birth time,
from st_birthtimespec on macOS/BSDs) — as BrightDate
decimals by default. Use -r for raw Unix seconds,
-r -s for both side-by-side, or
-F fmt for strftime.
-rw-r--r-- 1 jessica staff 55082 9628.198451 README.md
$ stat README.md
device 16777232
inode 117800042
mode -rw-r--r--
nlink 1
uid jessica
gid staff
rdev 0
size 55082
atime 9628.199840
mtime 9628.198451
ctime 9628.198451
blksize 4096
blocks 112
link
btime 9628.198451
$ stat +mtime README.md
9628.198451
$ stat -r -s README.md
mode 33188 (-rw-r--r--)
uid 501 (jessica)
gid 20 (staff)
atime 1778604397 (9628.199840)
mtime 1778604277 (9628.198451)
ctime 1778604277 (9628.198451)
btime 1778604277 (9628.198451)
sched
Schedule commands at future BrightDate times. Accepts traditional
HH:MM:SS offsets, BrightDate float offsets (+0.020833
≈ 30 min), and absolute BrightDate values. List pending events
with bare sched.
sched +0.020833 echo hello # ~30 min from now
sched 9628.5 echo midnight # absolute BD
$ sched
1 9627.930118 echo hello
2 9628.500000 echo midnight
times builtin
Reports user and system CPU time (for the shell and its children)
in millidays rather than the traditional m:ss format
— uniform units across every time surface in BSH.
The conversion engine is the
brightdate
Rust crate, statically linked into the bsh binary via
a tiny FFI surface. No runtime dependencies. No subprocess
overhead. Same TAI/J2000 substrate as the Rust and npm libraries.
Module index: bsh/brightdate bsh/datetime bsh/files bsh/stat bsh/sdi
BSH extends zsh's glob qualifiers so .m, .a,
.c, and the new .b (birth time) accept
fractional decimal-day values. Filter files with
centiday precision (0.01 d = 864 s ≈ 14 min) directly in the shell —
and with .b, use a timestamp that touch
can never fake.
Start with two log files, old.log backdated 2 hours:
$ setopt extendedglob nullglob
$ touch old.log new.log
$ perl -e 'utime time()-7200, time()-7200, "old.log"'
$ echo *.log(.m-1) # within 1 day — both match, too broad
new.log old.log
$ echo *.log(.m-0.05) # within 0.05 d (~72 min) — precision cuts through
new.log
$ echo *.log(.m-0.01) # within centiday (~14 min) — only the fresh file
new.log
$ touch old.log # reset mtime — but birthtime is immutable
$ echo *.log(.m-0.01) # mtime fooled: both match now
new.log old.log
$ echo *.log(.b-0.01) # birthtime never lies — old.log was born 2 h ago
new.log
All unit suffixes accept fractional values: d (days,
default), h (hours), m (minutes),
s (seconds), w (weeks),
M (months). Combine with sort keys —
*.log(.b-1On) gives today's logs oldest-first;
*(ob) sorts everything by creation time.
bsh-inject is a
builtin that encrypts a credential payload read from stdin and emits
it as an
OSC 7777 terminal
escape sequence. The plaintext never appears in ps, the
shell environment, or command history. The paired macOS Desktop Agent
reads the escape from the terminal stream, decrypts it with the
session key it negotiated at login, and acts on the plaintext —
auto-filling credentials, injecting API tokens, or forwarding to a
keychain.
BSH opens a chmod 600 Unix socket and performs
an ephemeral Diffie-Hellman exchange with the Desktop Agent.
A 32-byte session key is derived via
HKDF-SHA256
— never written to disk, wiped with
OPENSSL_cleanse() on exit.
bsh-inject reads stdin and encrypts it with
AES-256-GCM. The --type and --context values
are passed as GCM
AAD —
bound into the auth tag so tampering with the metadata
invalidates the ciphertext.
The ciphertext is emitted as an
OSC 7777
escape — invisible in the terminal, invisible to
ps, absent from shell history.
The macOS Desktop Agent reads the escape from the terminal stream, verifies the GCM auth tag, and acts on the plaintext — auto-filling a login form, injecting an API token, or forwarding to the system keychain.
Full specification: RFC — Secure Semantic Data Injection via OSC 7777
BSH builds with the standard autoconf workflow inherited from zsh,
plus a Rust toolchain for the
brightdate-rust static library.
A C compiler (clang or gcc),
make, autoconf, and a recent Rust
toolchain (rustup,
stable channel). macOS, Linux, and *BSD are all supported.
git clone --recursive https://github.com/Digital-Defiance/bsh.git
cd bsh
./configure
make -j$(nproc 2>/dev/null || sysctl -n hw.ncpu)
make check # optional: run the test suite
sudo make install
echo "$(command -v bsh)" | sudo tee -a /etc/shells
chsh -s "$(command -v bsh)"
bsh -c 'date' # BrightDate, baked in
bsh -c 'echo $BRIGHTEPOCH'
bsh -c 'PROMPT="[%P] %# "; print -P "$PROMPT"'
Looking for a configuration framework? See Oh My Bsh — 300+ plugins and 150+ themes layered on top of BSH.
@brightchain/brightdateTypeScript/JavaScript library. Same J2000.0 / TAI semantics. npm · source
brightdate
Rust crate powering BSH internally. Also ships standalone CLI
tools (bdate,
btime, buptime, bcal,
bwatch) — the b- prefixed versions for
use outside BSH, where the native date
etc. still rule.
crates.io
·
source
The CLI tools and BSH itself are available via the Digital Defiance tap:
brew tap digital-defiance/tap
brew install bdate btime buptime bcal bwatch bsh