muschel 0.1.x — a Clojure(Script) library for parsing bash, gating it with an allow/deny permit, and running it through a pluggable host.
Built as the bash front-end for LLM agent shells: agents emit bash naturally, muschel walks the AST, classifies every call against your rules, and executes via a host you control. The same .cljc layer runs on JVM, babashka, and ClojureScript (Node + browser).
A few things that might be interesting:
• Hand-written parser, no instaparse — sci-safe, runs in bb without surgery.
• 50 POSIX builtins in pure 99% of the goawk corpus). Same source compiles for JVM, bb, Node, and browser; CI gates all three.
• Parse-time + runtime-hook permit check — catches .cljc* — cat, ls, grep, sed, find, jq, cp, mv, tee, redirects, pipes, sub-shells, sh -c nested re-entry — *plus a real awk subset (hand-written lex + parse + interp, $cmd args dynamic dispatch and lazy command substitution that purely-static gates miss.
• *Structural sandbox containment* via the muschel.fs protocol: paths outside the root return ENOENT, symlink escapes are blocked, env -i and host-env leaks are closed. DiskFS pins to a root; VirtualFS is in-memory.
• *Resource budgets (`deadline-interrupt`, step-interrupt, combine) + tracing hooks* (`on-tool` / on-fs / on-deny) — agents don't hang you, and you can see exactly what they did.
• Forkable sessions for multi-turn shells (atom default, optional spindel for time-travel).
• muschel.emit translates bash → idiomatic Clojure forms (`if` / reduce / loop / as->) — useful for "show me the Clojure equivalent" surfaces in agent UIs.
• *npm + TypeScript types* — the full sandbox runs in the browser, including the POSIX builtin set, against a virtual fs and tool registry. Same API shape as the Clojure side.
Try it:
• Browser playground: https://replikativ.github.io/muschel/playground/ — real cd, real pipes, real sed/awk. Try find . -type f | xargs grep -l muschel or awk -F : '{print $1}' /etc/passwd.
• GitHub: https://github.com/replikativ/muschel
• Clojars: org.replikativ/muschel {:mvn/version "0.1.10"}
• npm: npm install muschel
• babashka: bb exec "echo hi | tr a-z A-Z"
Built as part of agentic-harness work. Three-runtime CI (JVM + CLJS + bb) gates every release. Early days, feedback welcome. The harness work is part of #simmis.
Fulcro now does TUI’s, via CLJ or Babashka!
Announcing https://github.com/fulcrologic/fulcro-tui
• Try it out: Clone the repo and run bb run tui to see a demo
• Flex-box like layout
• Fulcro state management, and “remote” management (persistence abstraction of an IO layer)
• Uses JLine, which is available in Babashka now
• Already has decent number of interactive elements:
◦ inputs
◦ text area
◦ scrollable viewports
◦ modals/picker
• Screen resize detection
• Colors/reverse/bold
What’s NOT stable: The entry point may change slightly. This is an alpha release and is not 100% API stable, but the main changes will likely just be the entry point (and any refinements I need to make to Fulcro…the bb support there is preliminary). You can expect that any changes I do make will not be hard to port to.
@borkdude performance isn’t related to JLine at all. It’s my the “flex box layout” kind of stuff and over-rendering. I’m tuning that up now. Even without Display the actual terminal render is fast (like 30-60fps)
nice. we did solve some performance issues in charm.clj using Display
I’ll do that as a second pass if I see performance issues I care about, but given how dominating the other bits are right now I’ll start with those.
Display actually was a 2x performance reduction. not sure just yet if it might be worth it for some other aspect (like terminfo db) but so far it was a loss within bb. Just FYI after a lot of analysis on my own rendering system: “The dominant cost is paint+layout (~16–18 ms/frame), not serialization — and neither renderer touches that. Our serializer is already negligible; swapping it for Display only adds cost.”
That’s interesting
yeah, I’m getting 60fps on average now, so I’m in the “plenty good enough” area already. I basically threw in a mini-tufte implementation and measured everything. Charm’s design might just benefit from something in Display? Not sure.
If I remember correctly charm had its own virtual dom like thing and this was swapped with Display. But good enough is good enough.
@tony.kay Looks very interesting! I see you're not using Jline's Display yet. You can use that as a kind-of virtual dom to get faster rendering (if you need it). I noticed that switching between fields feels a bit laggy sometimes and that may help, but not sure.
Ah, didn’t realize that was there. I’m using the term double-buffering…but largely Claude is figuring out the JLine stuff 😄
I’ll tip it that direction
you can (make it) look at charm.clj as well: https://github.com/TimoKramer/charm.clj
got it working with Inspect already as well…so you can debug the TUI app using fulcro’s electron inspector
wow, sick
all you man…my architecture has been like this for years, but never had a reason to really push it to the terminal. Having bb expand to the point it’s at finally made it a “reasonable thing to want” 😄 Fast TUI startup is important.
NOTE: I will have a new alpha release tomorrow, and that’s where I’ll do all my renaming. I’m contemplating the final ns names now…this was a bit of a premature alpha, but I was excited 🤷 Stay tuned on #C015AL9QYH1
Amazing! I ve been trying to get into clojure and was looking into babashka to have very few dependencies to deal with. Do I need to know React to use Fulcro? I am not a big fan of React. It's all over the place for my taste. 🙂
@codecareerjumpstart The underlying framework to do the TUI stuff is Jline, which is built into babashka
it's a Java library though. Some libs on top of that make it easier to use. Fulcro and charm.clj being two of those
@borkdude Oh I see. No problem then. Can't wait to try it. Thank you for Babashka.
Fulcro completely hides React (for web use) and is designed to be UI agnostic, but it does mimic the idea that the view should be a “pure function of data” as opposed to a “mutable thing”. It also promotes application development as a combinations of functions that evolve a normalized state db instead of “experiment your UI into existence”. So, I’d say the learning curve of Fulcro itself is “a bit steeper than others” because so much about it is different than mainstream. Charm is probably more approachable to for smaller things
Thanks for your interest. You have an interesting name though, for a minute the admin team thought you were a spam account :)
@tony.kay would you say fulcro is similar to re-frame in that it has a db for state? or does that db live on the server side?
Charm.clj is modeled after the Elm architecture
(which sounds similar)
That’s a great question, and I think a source of great confusion to the community in general. Fulcro has a number of things going on. A local, simple ,normalized db in the client is a central feature. There is a difference in that Fulcro has an opinion of how you should structure your data. Fulcro also has opinions on how you should interact with “remotes” (sources of async data) that abstract them and cover a number of difficult distributed system concerns. It is much less about the UI than the complex problems that appear at scale. IMO, UI is the least interesting problem to solve (Fulcro’s UI bits cover about 10 lines of code…convert db -> ui props, call a fn that can turn that into the current frame). The more interesting problem is how to make that work in an overall complex system that has interactions with distributed async sources of data (a specialization of which is an http server API). Quite a bit of the library surface area is about managing the database, the asynchrony, the process (e.g. UI state machines and statecharts), and the abstraction of service (e.g. through Pathom/EQL). So, unless you’re trying to write a terminal-based accounting system like an old-school client/server system, it’s actually a bit of overkill 😄 But it make me happy to be able to use it for the things I do…
@borkdude Sorry for my nickname. I almost never use Slack. Clojure is the only reason why I have an account in slack. it did use my email by authenticating over oauth2. I was surprised to see that. Changed it now 🙂
@tony.kay I have watched some videos on youtube today about fulcro and it's really intriguing. I was wondering whether it is optimized for internal application (backoffices, dashboard ..) or can it also be use for internet applications?
It’s general purpose and highly optimized; but it is data-centric and a lot of the surface is written with forms/reports in mind. If you’re interested in smaller, more UI-focused with less need for structured data and data processing, then you’d be better off aiming at something that is more about “rendering” and less about “data”. I’m a very functional/data-driven kind of guy. Graphics are interesting to me, but UI isn’t. Fulcro is about turning what I consider to be drudgery (UI work) into something that I can export to someone else 😄 None of the I/O, logic, processing, or serious thought should happen there. When I say “there” I mean in the UI code itself. There can be a lot of logic in the client, in fact I like that very much (using someone else’s compute instead of mine)…but the logic should not be in the code that represents the graphical UI elements of that client…just to be clear. If you want to write a game or a flashy website (or most TUIs for that matter 😜 ), Fulcro’s not the best fit.