2026-08-17 22:30:18 -04:00
<!doctype html>
< html lang = "en" >
< head >
< meta charset = "utf-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1" >
< title > Self-Healing Autopoietic Shell</ title >
< style >
: root {
--bg : #0b0d10 ; --panel : #12151a ; --ink : #e6e9ef ; --dim : #8b93a1 ;
--accent : #7c9eff ; --ok : #5fd88f ; --warn : #f2b64b ; --err : #ff6b6b ;
--border : #232833 ;
}
* { box-sizing : border-box ;}
body {
margin : 0 ; background : var ( -- bg ); color : var ( -- ink );
font : 15 px / 1.55 ui-monospace , SFMono-Regular , Menlo , Consolas , monospace ;
}
header {
padding : 2.5 rem 1.5 rem 1.25 rem ; max-width : 900 px ; margin : 0 auto ;
}
h1 { font-size : 1.4 rem ; margin : 0 0 .4 rem ; font-weight : 600 ;}
header p { color : var ( -- dim ); margin : .2 rem 0 ; font-size : .92 rem ;}
2026-08-17 22:43:32 -04:00
. runbox {
max-width : 900 px ; margin : 0 auto 1.5 rem ; padding : 0 1.5 rem ;
}
. runbox-label { font-size : .78 rem ; text-transform : uppercase ; letter-spacing : .06 em ; color : var ( -- dim ); margin-bottom : .4 rem ;}
. runbox-cmd {
display : flex ; align-items : stretch ; gap : 0 ; background : var ( -- panel );
border : 1 px solid var ( -- accent ); border-radius : 8 px ; overflow : hidden ;
}
. runbox-cmd code {
flex : 1 ; padding : .75 rem .9 rem ; font-size : .82 rem ; overflow-x : auto ;
white-space : pre ; color : var ( -- ok );
}
. runbox-cmd button {
flex-shrink : 0 ; background : var ( -- accent ); border : 0 ; color : #0b0d10 ;
font : inherit ; font-weight : 600 ; font-size : .8 rem ; padding : 0 1.1 rem ; cursor : pointer ;
}
. runbox-cmd button : hover { opacity : .9 ;}
. runbox-cmd button . copied { background : var ( -- ok );}
. runbox-note { color : var ( -- dim ); font-size : .8 rem ; margin-top : .5 rem ; line-height : 1.5 ;}
. runbox-note code { background : #171b22 ; padding : .05 rem .3 rem ; border-radius : 4 px ;}
2026-08-17 22:30:18 -04:00
main { max-width : 900 px ; margin : 0 auto ; padding : 0 1.5 rem 3 rem ; display : grid ; gap : 1.25 rem ; grid-template-columns : 1 fr ; }
@ media ( min-width : 760px ) { main { grid-template-columns : 1.3 fr .9 fr ;} }
. panel {
background : var ( -- panel ); border : 1 px solid var ( -- border ); border-radius : 10 px ;
overflow : hidden ;
}
. panel h2 {
font-size : .78 rem ; text-transform : uppercase ; letter-spacing : .06 em ; color : var ( -- dim );
margin : 0 ; padding : .7 rem .9 rem ; border-bottom : 1 px solid var ( -- border );
}
# term {
padding : .9 rem ; height : 360 px ; overflow-y : auto ; white-space : pre-wrap ; word-break : break-word ;
font-size : .88 rem ;
}
# term . line { margin : 0 0 .15 rem ;}
. prompt { color : var ( -- accent );}
. learn { color : var ( -- warn );}
. ok { color : var ( -- ok );}
. err { color : var ( -- err );}
. dim { color : var ( -- dim );}
form { display : flex ; border-top : 1 px solid var ( -- border );}
form span { padding : .6 rem .9 rem ; color : var ( -- accent );}
input {
flex : 1 ; background : transparent ; border : 0 ; color : var ( -- ink ); font : inherit ;
padding : .6 rem .9 rem .6 rem 0 ; outline : none ;
}
# pfile { padding : .9 rem ; min-height : 120 px ; font-size : .85 rem ;}
# pfile . row { color : var ( -- ok ); margin : 0 0 .3 rem ;}
# pfile . empty { color : var ( -- dim );}
. try { padding : .9 rem ; border-top : 1 px solid var ( -- border ); display : flex ; flex-wrap : wrap ; gap : .4 rem ;}
. try button {
background : #171b22 ; border : 1 px solid var ( -- border ); color : var ( -- ink );
font : inherit ; font-size : .78 rem ; padding : .35 rem .6 rem ; border-radius : 6 px ; cursor : pointer ;
}
. try button : hover { border-color : var ( -- accent ); color : var ( -- accent );}
code { background : #171b22 ; padding : .1 rem .35 rem ; border-radius : 4 px ; font-size : .85 em ;}
pre {
background : #171b22 ; padding : .9 rem ; border-radius : 8 px ; overflow-x : auto ;
font-size : .82 rem ; border : 1 px solid var ( -- border ); margin : .8 rem 1.5 rem 0 ; max-width : 900 px ;
}
footer { max-width : 900 px ; margin : 0 auto ; padding : 0 1.5 rem 3 rem ; color : var ( -- dim ); font-size : .82 rem ;}
footer a { color : var ( -- accent );}
. reset { color : var ( -- dim ); font-size : .78 rem ; background : none ; border : 0 ; cursor : pointer ; text-decoration : underline ; padding : 0 ;}
</ style >
</ head >
< body >
< header >
< h1 > 🔁 Self-Healing Autopoietic Shell</ h1 >
< p > A shell function that learns from its own failures — run a command, teach it a fix when it fails, and it never fails that way again.</ p >
2026-08-17 22:43:32 -04:00
< p class = "dim" > The simulation below is a browser mockup, not a real shell — this page is static, so nothing here can actually execute anything. To run the real thing in your real shell:</ p >
2026-08-17 22:30:18 -04:00
</ header >
2026-08-17 22:43:32 -04:00
< div class = "runbox" >
< div class = "runbox-label" > run this in your terminal — no git clone needed</ div >
< div class = "runbox-cmd" >
< code id = "bootstrapCmd" > eval "$(curl -fsSL https://huggingface.co/spaces/Daveswo/self-healing-autopoietic-shell/raw/main/contrib/fx/bootstrap.sh)"</ code >
< button id = "copyBtn" type = "button" > copy</ button >
</ div >
< div class = "runbox-note" > fetches < code > f()</ code > , < code > fx()</ code > , and all default fix-sources into a temp dir and sources them into your < em > current</ em > shell — add the same line to your rc file to keep it every session.</ div >
</ div >
2026-08-17 22:30:18 -04:00
< main >
< div class = "panel" >
< h2 > Simulated shell</ h2 >
< div id = "term" ></ div >
< form id = "form" >
< span > $ f</ span >
< input id = "cmdInput" autocomplete = "off" placeholder = "cat needs-fix.txt" autofocus >
</ form >
< div class = "try" >
< button data-cmd = "cat needs-fix.txt" > cat needs-fix.txt</ button >
< button data-cmd = "curl api.example.com" > curl api.example.com</ button >
< button data-cmd = "echo already-fine" > echo already-fine</ button >
</ div >
</ div >
< div class = "panel" >
< h2 > p < span class = "dim" style = "text-transform:none;" > (learned fixes)</ span ></ h2 >
< div id = "pfile" >< div class = "empty" > // empty — nothing learned yet</ div ></ div >
< div class = "try" >
< button class = "reset" id = "resetBtn" > reset memory</ button >
</ div >
</ div >
</ main >
< pre > f() {
FIX=""
if [ -f p ]; then
while IFS= read -r line; do
case "$line" in
"$*="*) FIX="${line#"$*="}" ;;
esac
done < p
fi
until { eval "$ FIX " 2 > /dev/null; "$@"; }; do
printf '\n[LEARN] "%s" failed. Enter a fix (blank to give up): ' "$*" >& 2
read -r n
[ -n "$n" ] || return 1
echo "$*=$n" >> p
FIX="$n"
done
}</ pre >
< footer >
Real source, tests, and design notes are in the repo alongside this page —
see < code > src/f.sh</ code > , < code > test/test_f.sh</ code > , and < code > docs/DESIGN.md</ code > .
</ footer >
< script >
( function (){
const term = document . getElementById ( 'term' );
const form = document . getElementById ( 'form' );
const input = document . getElementById ( 'cmdInput' );
const pfileEl = document . getElementById ( 'pfile' );
const resetBtn = document . getElementById ( 'resetBtn' );
// "p" — the learned-fixes store. Simulated filesystem state lives here.
let p = {}; // command -> fix
let fs = {}; // simulated tiny filesystem for the demo commands
let awaitingFix = null ; // command string we're currently learning a fix for
function print ( text , cls ){
const div = document . createElement ( 'div' );
div . className = 'line' + ( cls ? ' ' + cls : '' );
div . textContent = text ;
term . appendChild ( div );
term . scrollTop = term . scrollHeight ;
}
function renderP (){
const keys = Object . keys ( p );
if ( ! keys . length ){
pfileEl . innerHTML = '<div class="empty">// empty — nothing learned yet</div>' ;
return ;
}
pfileEl . innerHTML = keys . map ( k =>
`<div class="row"> ${ escapeHtml ( k ) } = ${ escapeHtml ( p [ k ]) } </div>`
). join ( '' );
}
function escapeHtml ( s ){
return s . replace ( /[&<>"']/g , c => ({ '&' : '&' , '<' : '<' , '>' : '>' , '"' : '"' , "'" : ''' }[ c ]));
}
// Applies a learned fix (or a freshly supplied one) to the tiny simulated fs/state.
function applyFix ( fix ){
const m = fix . match ( /^echo\s+(.*?)\s*>\s*(\S+)$/ );
if ( m ){
let val = m [ 1 ]. trim ();
if (( val . startsWith ( '"' ) && val . endsWith ( '"' )) || ( val . startsWith ( "'" ) && val . endsWith ( "'" ))){
val = val . slice ( 1 , - 1 );
}
fs [ m [ 2 ]] = val ;
return ;
}
if ( /^(export\s+)?API_KEY=/ . test ( fix )){ fs [ '__api_key' ] = true ; return ; }
}
// Runs one of the demo commands against simulated state. Returns {ok, out}.
function runCommand ( cmd ){
if ( cmd === 'cat needs-fix.txt' ){
if ( fs [ 'needs-fix.txt' ] !== undefined ) return { ok : true , out : fs [ 'needs-fix.txt' ]};
return { ok : false , out : 'cat: needs-fix.txt: No such file or directory' };
}
if ( cmd === 'curl api.example.com' ){
if ( fs [ '__api_key' ]) return { ok : true , out : '{"status":"ok"}' };
return { ok : false , out : 'curl: (401) Unauthorized — missing API_KEY' };
}
if ( cmd . startsWith ( 'echo ' )){
return { ok : true , out : cmd . slice ( 5 )};
}
return { ok : false , out : cmd + ': command not found' };
}
function tryCommand ( cmd ){
if ( p [ cmd ]) applyFix ( p [ cmd ]);
const res = runCommand ( cmd );
if ( res . ok ){
print ( res . out , 'ok' );
return ;
}
print ( res . out , 'err' );
print ( `[LEARN] " ${ cmd } " failed. Enter a fix (blank to give up):` , 'learn' );
awaitingFix = cmd ;
}
form . addEventListener ( 'submit' , function ( e ){
e . preventDefault ();
const val = input . value ;
input . value = '' ;
if ( awaitingFix ){
print ( '> ' + ( val || '(blank)' ), 'dim' );
if ( ! val . trim ()){
print ( `f: giving up on " ${ awaitingFix } "` , 'err' );
awaitingFix = null ;
return ;
}
p [ awaitingFix ] = val . trim ();
renderP ();
applyFix ( val . trim ());
const cmd = awaitingFix ;
awaitingFix = null ;
const res = runCommand ( cmd );
print ( res . ok ? res . out : res . out , res . ok ? 'ok' : 'err' );
if ( ! res . ok ){
print ( `[LEARN] " ${ cmd } " failed. Enter a fix (blank to give up):` , 'learn' );
awaitingFix = cmd ;
}
return ;
}
if ( ! val . trim ()) return ;
print ( '$ f ' + val , 'prompt' );
tryCommand ( val . trim ());
});
document . querySelectorAll ( '.try button[data-cmd]' ). forEach ( btn => {
btn . addEventListener ( 'click' , () => {
input . value = btn . dataset . cmd ;
input . focus ();
});
});
resetBtn . addEventListener ( 'click' , () => {
p = {}; fs = {}; awaitingFix = null ;
renderP ();
term . innerHTML = '' ;
print ( '// memory reset — p is empty again' , 'dim' );
});
print ( '// try: cat needs-fix.txt' , 'dim' );
print ( '// it will fail once — teach it a fix like: echo hello > needs-fix.txt' , 'dim' );
})();
2026-08-17 22:43:32 -04:00
( function (){
const btn = document . getElementById ( 'copyBtn' );
const codeEl = document . getElementById ( 'bootstrapCmd' );
if ( ! btn || ! codeEl ) return ;
btn . addEventListener ( 'click' , async () => {
try {
await navigator . clipboard . writeText ( codeEl . textContent );
} catch ( e ){
const range = document . createRange ();
range . selectNode ( codeEl );
window . getSelection (). removeAllRanges ();
window . getSelection (). addRange ( range );
document . execCommand ( 'copy' );
window . getSelection (). removeAllRanges ();
}
const original = btn . textContent ;
btn . textContent = 'copied' ;
btn . classList . add ( 'copied' );
setTimeout (() => { btn . textContent = original ; btn . classList . remove ( 'copied' ); }, 1500 );
});
})();
2026-08-17 22:30:18 -04:00
</ script >
</ body >
</ html >