4.1 C
Canberra
Thursday, May 21, 2026

Agentic Bash | Cocoanetics


The elements I’ve been saying not too long ago definitely hinted at what I’m engaged on in the intervening time. A bash playground that lets me train SwiftBash, SwiftScript and SwiftPorts all tied collectively through ShellKit. There was one half that was on my non-public repo: the agentic harness and pure Swift wrappers for OpenAI APIs. I stored considering that if I needed to finally make my Bash Playground public, then I wanted to even have this closing half on GitHub as properly.

My mission assertion for iBash is to have a common app that offers me a digital shell with a workspace in a file bundle that may do a lot of the scripting and enhancing work one would wish to do cell plus a coding agent that lives and works in these sandboxes.

This Coder agent is modelled after PI, with the very same instruments that PI has. Plus two additions: The newest OpenAI fashions are skilled on enhancing information with the apply_patch software, so I’m utilizing this as an alternative of PI’s search-replace. Additionally there’s a sub_agent software as a result of this manner Coder can do a little bit of exploring with its personal context window and may then come again with its findings to the principle once more with out bloating the principle context window.

The entire thing has gotten to the extent the place I can ask the agent to go searching on this bash sandbox and attempt to discover issues that don’t work as they need to. Then it may doc the issues it finds in native markdown information and likewise use the gh software (from SwiftPorts) to open new GitHub points with the steps to breed the problem.

The I can have Claude iron out these wrinkles one after the other. Take for instance difficulty 46 from the screenshot above. My claude made PR 54 for that, after asking me through the Claude cell app an structure query. It resolved a assessment remark from codex, babysat the construct till all platforms have been inexperienced. On the finish I might simply merge the PR and delete the department.

My hope is that if I hold doing this loop lengthy sufficient that the floor of the bash instructions in SwiftBash will turn into indistinguishable from actual bash. An agentic self-improvement loop.

Let’s go over all my OSS tasks and see what’s new.

SwiftText: I’ve been writing a markdown parser for no cause

swifttext had a hand-rolled markdown parser that I’d been patching for over a yr. Each time one thing rendered weirdly in a PDF, I’d open MarkdownLexer.swift, discover the sting case, add one other regex, ship it.

Then final week I went swift-markdown — Apple’s personal markdown library, sitting at github.com/swiftlang/swift-markdown, utilized by DocC, completely maintained, with the complete CommonMark + GFM AST floor I’d been attempting to approximate by hand. I’d been ignoring it for years as a result of I assumed it was DocC-internal.

It’s not DocC-internal. It’s a Swift bundle. You may simply use it. I admit that I’ve a extreme case of “not invented right here” syndrome, however for Apple I make an exception…

SwiftText 1.1.9 replaces my parser with swift-markdown. Picture alt-text now traverses nested inline content material accurately (which my parser had been silently flattening), and the PDF renderer not forces a web page break earlier than each H1/H2 — so lengthy technical paperwork cease losing paper between each part.

There was one factor although that Apple’s markdown parser continues to be missing: it doesn’t deal with footnotes. However I’m able to work round this with a pre- and post-processing step.

SwiftMCP: the */ bug, and a solution to cut up servers

The bug-of-the-week award goes to a macro-expansion regression in SwiftMCP 1.4.5-original. I had generated documentation feedback as /** ... */ blocks. The issue: if anybody (together with me) wrote a docstring containing */ — mostly "**/*" in a glob instance — the doc block closed early and the remaining spilled into uncooked Swift supply, producing cascades of “unterminated string literal” errors with no apparent trigger. Switching to /// line feedback mounted it. The v1.4.5 tag was re-pointed on the repair; 1.4.6 widens the swift-syntax vary so SwiftMCP coexists peacefully with SwiftScript.

Extra attention-grabbing structurally: @MCPExtension. Now you can annotate extension YourServer in any file and even some other goal with @MCPExtension, and the instruments/assets/prompts outlined there get aggregated into the first @MCPServer. The generated Shopper floor is prolonged in lock-step, so callers see one shopper no matter which goal a given software lives in. This was the architectural piece I wanted for big MCP servers to cease ballooning into single-file monoliths.

SwiftMail: the Proton Mail Bridge incident

Somebody tried to make use of SwiftMail with Proton Mail Bridge, which runs on a non-standard native port with out conventional STARTTLS semantics, and found that my “infer TLS from the port quantity” heuristic guessed flawed. Fixing it correctly meant exposing an express MailTransportSecurity enum — .computerized (the outdated guesser), .implicitTLS, .requiredSTARTTLS, .plaintext — so callers can override the inference.

The larger repair was much less glamorous however most likely impacts extra individuals: envelope-date parsing. I’d been strict about RFC 5322 dates, which sounded cheap till I attempted to index a 15-year-old mailbox and watched hundreds of “couldn’t parse date” warnings scroll previous. Actual mail within the wild makes use of lowercase month names, omits time zones, embeds (UTC) parentheticals, and nonetheless makes use of out of date US zone abbreviations like PST. SwiftMail 1.6.4 accepts all of these and stops complaining.

There’s additionally an MIME repair that I’m barely embarrassed by: HTML emails with attachments have been lacking a closing boundary, so strict parsers have been treating the attachment as nonetheless nested contained in the HTML half. It rendered high-quality in Gmail and Apple Mail, however extra pedantic shoppers would mangle it. Now mounted.Publish: the downstream beneficiary

Publish is the IMAP/SMTP daemon and CLI that’s mainly my testbed for every thing above. The v1.6.6 launch shipped this week and is, by my very own admission, essentially the most boring launch notes I’ve ever written: not a single line of Publish’s personal code modified. It’s pure dependency uptake.

However that uptake issues, as a result of every thing from SwiftMail’s higher date parsing and MIME repair, SwiftMCP’s base64 binary correction, and SwiftText’s PDF page-break repair lands in put up and postd mechanically. put up ship now produces strictly-correct MIME for HTML-plus-attachment messages, put up fetch stops complaining about 15-year-old date strings, put up pdf not wastes paper earlier than each heading, and the MCP daemon round-trips attachment bytes accurately. The purpose of the layered stack is that releases like this are allowed to be boring.

SwiftPorts: bringing the terminal to life

If the SwiftText story is about deleting a parser, the SwiftPorts story is about including one again in a spot it really belonged.

GlamKit is the headline. It’s a pure-Swift port of Appeal’s Glamour — markdown → ANSI rendering. The gh repo view and glab repo view instructions now render the README proper in your terminal, with syntax-highlighted code blocks, actual GFM tables drawn with box-drawing characters, and correctly themed headings. It makes use of swift-markdown for the parse step (see above), so the AST dealing with is stable; I solely needed to write the ANSI styling layer on high.

After I added the software backing for Coder I discovered that PI is utilizing rg aka ripgrep fd for discover – so naturally I wanted so as to add these as ports to the gathering. And I discovered the grep subcommand was lacking from the git port as properly.

  • RipgrepKit — a pure-Swift port of BurntSushi/ripgrep. It now reads international gitignore, walks mum or dad directories for repository ignore inheritance, and matches upstream rg behaviour shut sufficient that I’ve been utilizing it as my each day rg.
  • FdKit — pure-Swift port of sharkdp/fd with LS_COLORS assist, match highlighting, the works.
  • git grep — lastly added as a subcommand within the swiftgit port.

The pace at which we’re including Swift ports of well-known utilities to SwiftPorts is making my head spin. A lot of the work additionally went into sandboxing assist. The place libraries and utilities use FileManager.default for accessing information we’ve got no solution to block file entry. So the one manner is to sprinkle in lots of permission checks earlier than handing over a path.

SwiftBash: 100 small issues

SwiftBash obtained essentially the most commits of any repo this fortnight, however only a few of them are headline-worthy individually. It’s the thousand-paper-cuts part the place each script somebody runs surfaces yet another factor the interpreter dealt with subtly flawed.

The sample that shocked me most: [ -t N ] (the test-if-fd-is-a-tty verify that each colour-detection idiom depends on) and $'...' (ANSI-C quoting). I’d shipped with out them as a result of no script in my very own assortment used them, however each well-written CLI makes use of them to resolve whether or not to emit color. As soon as these landed, half my very own ported instruments immediately began auto-detecting terminals accurately.

Different notable bits:

  • Bun’s JavaScriptCore on Linux, Home windows, and Android. The JSC put up talked about Apple platforms; SwiftBash 1.5-line picks up Bun’s prebuilt JavaScriptCore in every single place else, so swift-js now boots a full JS runtime on platforms the place Apple doesn’t ship JSC in any respect.
  • much less and extra as in-process pager builtins. No exterior course of, paging respects the sandbox.
  • Mode flags -e / -u / -x / -v — each “set -euo pipefail” script you’ve ever seen now really behaves as supposed.
  • compgen plus public completion sources, so embedders can hook tab-completion into their very own UIs.
  • ${var:offset:size} with full nesting — the offset can itself be a substitution expression. Bash has been doing this for many years; my parser was bailing on the primary nested brace.

ShellKit: the contract beneath

Most readers received’t contact ShellKit immediately, however it’s the rationale the opposite repos compose with out round dependencies.

ShellKit is the abstraction layer for “what’s the shell surroundings, actually?” — stdin/stdout/stderr sinks, surroundings, sandbox coverage, community coverage, the method desk, and the binary catalog. The default is host-system passthrough; embedders override per-task. Each CLI software I publish reaches host assets solely by Shell.present, by no means FileManager or Basis.Course of immediately. That’s what makes the identical rg / fd / much less / bash binary work the identical manner whether or not you run it from an actual terminal, from inside SwiftBash, or from inside a sandboxed iOS app.

This fortnight ShellKit picked up the Shell.processLauncher subprocess primitive (so embedders can intercept course of launches with out monkey-patching), a cleaner Sandbox.Denial description that doesn’t leak absolute host paths into error messages, and a way more sincere BinCatalog that is aware of in regards to the script interpreters, git/gh/glab, the compression household, and the platform-specific binaries. CI now runs on macOS, iOS, Linux, Home windows, and Android.

I additionally needed to have correct assist for compgen – the bash manner of tab completion in addition to genuine dealing with of $PATH. All instructions now present in one of many customary bin folders or as builtin.

SwiftScript: a Swift interpreter that respects your sandbox

SwiftScript runs .swift information with out swiftc. The latest work routes each Basis IO door — file reads, community calls, course of launch, identification lookups, exit — by Shell.present. Mixed with SubprocessModule bridging import Subprocess to Shell.processLauncher, now you can embed a Swift interpreter in your app and have the script actually unable to flee your sandbox, even when it calls Subprocess.run.

It’s the identical thought as JavaScriptCore from final put up, utilized to Swift itself. Essentially the most satisfying half: a third-party .swift file can import Basis, write essentially the most innocent-looking attempt Information(contentsOf:), and nonetheless hit your sandbox boundary as an alternative of the consumer’s house listing.

SwiftAgents: opening the field

That is the massive one for me. SwiftAgents is the LLM-and-agents SDK that’s been sitting inside a personal repo referred to as AgentCorp for the higher a part of two years, quietly doing the precise work behind virtually every thing else I ship. It’s now open on GitHub.

The form of it: pure, stunning Swift wrappers across the LLM APIs as they really evolve. I began writing it when OpenAI nonetheless solely had the Completions endpoint. Then I rewrote the floor for Assistants. Then for Responses. The present incarnation additionally covers Conversations, and the entire thing is structured as a Swift port of the OpenAI Brokers SDK — modelled after their abstractions, however expressed in idiomatic Swift, with robust typing, async/await, and the sort of API floor that looks like Basis relatively than a transpiled Python shim.

There are two pattern apps, one is Coder CLI – a primary coding agent for the terminal. The opposite is an actual time voice agent I’m tinkering with.

The realtime voice agent permits you to cellphone with a handy guide a rough and sensible voice agent that may edit information within the app’s paperwork folder through its built-in coding agent. It transcribes the dialog and it has the flexibility to ask OpenClaw through the chat completions API. This was the check mattress for including realtime session assist to SwiftAgents.

Subsequent Steps

Actually, I don’t know if the realtime agent even works at this level, the primary large step was to get all of it onto GitHub. Subsequent I’ll must ensure that it’s nonetheless working with the modified and unified dependencies. As soon as I’ve it working once more, I’ll remember to present it off in a video.

Additionally iBash is rising in leaps and bounds and I’m trying ahead to providing you with a tour of it quickly. I’m hesitant to open supply it as a result of I’d wish to put it on the app retailer first. Additionally perhaps do an open beta with Testflight. That may be enjoyable and assist me discover extra points.

After which there are some additions to the LLM APIs that I wish to do in my SDK. OpenAI not too long ago added the potential of calling their APIs through internet sockets, so most likely that. Completely satisfied to listen to your ideas and concepts on any of the above!


Classes: Administrative

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

[td_block_social_counter facebook="tagdiv" twitter="tagdivofficial" youtube="tagdiv" style="style8 td-social-boxed td-social-font-icons" tdc_css="eyJhbGwiOnsibWFyZ2luLWJvdHRvbSI6IjM4IiwiZGlzcGxheSI6IiJ9LCJwb3J0cmFpdCI6eyJtYXJnaW4tYm90dG9tIjoiMzAiLCJkaXNwbGF5IjoiIn0sInBvcnRyYWl0X21heF93aWR0aCI6MTAxOCwicG9ydHJhaXRfbWluX3dpZHRoIjo3Njh9" custom_title="Stay Connected" block_template_id="td_block_template_8" f_header_font_family="712" f_header_font_transform="uppercase" f_header_font_weight="500" f_header_font_size="17" border_color="#dd3333"]
- Advertisement -spot_img

Latest Articles