Previously fx() stripped the "[source-label]" prefix before handing a chosen fix to f(), so once a fix landed in p, a manually-typed fix, a locally-known fix, and an LLM-guessed fix (70-local-llm.sh, 80-remote-api.sh) were byte-for-byte indistinguishable. That silently undermines 80-remote-api.sh's own documented trust boundary, which requires LLM-sourced fixes to stay visually distinguishable from verified ones -- and the distinction was permanently lost once p is disk-persisted across a reboot (adaptive-loop.sh). fx() now records "cmd=source-file" to FX_TRACE_FILE (default ./p.trace) alongside every fix it hands to f(), using the same "record intent, not confirmed success" timing f() already uses for p itself. Verified end-to-end against a stub 80-remote-api.sh-style source: p and p.trace both populate correctly, and the retried command actually succeeds.
title, emoji, colorFrom, colorTo, sdk, pinned, license, license_name, license_link
| title | emoji | colorFrom | colorTo | sdk | pinned | license | license_name | license_link |
|---|---|---|---|---|---|---|---|---|
| Self-Healing Autopoietic Shell | 🔁 | indigo | purple | static | false | other | use-only-no-modify-no-sell | LICENSE |
Self-Healing Autopoietic Shell
A shell function that learns from its own failures and doesn't fail the same way twice.
What it does
run command → fails → ask for a fix → persist the fix → retry → succeed
The next time that exact command is run, the learned fix is applied automatically before the command itself — no failure, no prompt. The knowledge lives in a plain text file (p) that you can copy to any other machine to transfer what this shell has learned.
- Zero infrastructure. Pure POSIX shell. No database, no ML model, no network calls.
- Transferable cognition.
pis justcommand=fixlines.scp p otherhost:~/pand the other machine inherits every fix you've ever taught this one. - Self-modifying, not self-executing. It never guesses a fix on its own — a human (or another process) supplies it once, and the loop remembers it forever after.
The pattern (41 bytes)
f(){ $@||{read x&&bash -nc$x&&echo$x>>p&&eval$x&&f"$@";};}
This is the minimal, unapologetically golfed core: run $@; if it fails, read a replacement command, sanity-check it parses, log it to p, eval it, and recurse. It's the idea in its smallest possible form — fragile on purpose, to show the mechanism with nothing hidden.
The hardened version (src/f.sh)
The golfed version above breaks on quoting, doesn't distinguish between different failing commands, and recurses instead of looping. src/f.sh is a POSIX-portable version used in production (it's what boots inside AdaptiveOS):
f() {
FIX=""
while IFS= read -r line; do
case "$line" in
"$*="*) FIX="${line#"$*="}" ;;
esac
done < p
until { eval "$FIX" 2>/dev/null; "$@"; }; do
printf '\n[LEARN] "%s" failed. Enter a fix: ' "$*"
read -r n
[ -n "$n" ] || return 1
echo "$*=$n" >> p
FIX="$n"
done
}
Differences from the 41-byte original:
- Looks up the fix keyed by the exact command, so
pcan hold fixes for many different failing commands, not just the last one. - Uses
until/loop instead of self-recursion. - Applies the learned fix proactively on every subsequent call, not just after a fresh failure.
Usage
. src/f.sh
f cat /etc/myapp.conf
# [LEARN] "cat /etc/myapp.conf" failed. Enter a fix (blank to give up):
# > echo "port=8080" > /etc/myapp.conf
Note the fix isn't a replacement for the command — it's a precondition that runs immediately before the original command is retried. f always re-runs the exact command you asked for; the fix's job is to make the environment one where that command now succeeds (create a missing file, export a variable, start a service, etc.).
Run it again later — even in a new shell, as long as p is in the working directory — and it applies the fix silently.
Why "autopoietic"
Autopoiesis (Maturana & Varela) describes systems that produce and maintain themselves through their own operation — a cell doesn't have external code telling it how to be a cell; the process of living is the process of continuously rebuilding itself. f() is a toy version of that idea applied to a shell: the artifact that results from running it (p, the accumulated fixes) changes how the function itself behaves on the next call. The shell is, in a small way, writing its own patches.
See docs/DESIGN.md for more on the mechanism and its limits.
Try it
Open index.html (or this Space) for an interactive in-browser simulation of the learn/fix/retry loop — no shell required.
Files
src/f.sh— the hardened, sourceable implementationindex.html— interactive browser demodocs/DESIGN.md— design notes, the autopoiesis framing, known limitationstest/test_f.sh— automated test of the learn → persist → auto-apply cycle