HN user

jonnyasmar

53 karma

Building getatrium.dev -- software engineer of 25+ years that doesn't write code anymore... I just specialize in talking to AI now. What a weird time to be alive.

Posts4
Comments33
View on HN

Since I built my own dev tool to allow me to better organize and manage multiple sessions, I've found my flow state hits when I've got agents staggering to completion. Conversation with one, wrap it up, send my response, and another one finishes. I currently have 49 agent sessions open in atrium and when I'm grinding, 5-15 are going at a time. If I get em all onto longer horizon tasks, I start to comb through other sessions to pick up parked conversations.

Honestly, it was about 4-6 hours of hands on keyboard. Bout a day and a half overall with a handful of smaller tweaks/bugfixes since then. I am definitely planning on writing about it. tl;dr this was sort of glorified vibe-coding and intentionally so in order to really see what 4.8 was capable of. But I do have some interesting observations that I made along the way that I'm going to go into more detail about.

Thanks! So the persistence is universal. atrium allows you to instantly pick up where you left off across all of your projects/sessions/etc. Start a conversation, leave it to work on something else, restart, and it auto-resumes so you can pick it up again later. Additionally, your sessions are indexed to allow for FTS and every interaction is stored in a timeline that you can use to easily (re)orient yourself in any project.

Happy to go into more detail, but that's kinda the high-level of the persistence story.

When the goal of that function is to think (a notoriously human behavior), it's perfectly understandable to anthropomorphize it.

The reality is that there are people that want AI in everything they use and there are people that don't. Google, like almost every other big tech company, is betting that there are more of the former.

And now we have an arms race with benefits nobody knew they needed and consequences nobody asked for.

Essentially :( I recently built a tool for managing many agents simultaneously and decided to focus 100% on CLI-first cause I saw that coming.

It's a massive bait & switch, honestly. I can't imagine how many hours/tokens were spent collectively building SDK-based tools on the premise of subscription pricing.

Super interesting mental model here. I'm building a tool, called atrium, that set out to solve similar problems, but I landed on a pretty different model -- workspace > room > stack > pane. I'm really curious to understand more about your concept of topologies, though. How exactly does it manifest in practice? Are they essentially organized units of collaborative work that your agents are executing? Has this unlocked different ways to solve problems for you than you were doing before or is it primarily organizational sugar?

At any rate -- really cool concept. Wish you the best of luck with it!

I bet if sites just added a "likely AI-generated" badge next to UGC, 99% of people would stop doing this. Problem is, without public shaming, many people will continue to take advantage of anything that requires them to do/think less.

Gemini CLI is so incomprehensibly bad. I can only hope dedicated focus on agy will be the difference maker. It'd be nice to actually be able to integrate Gemini models into my workflows because they offer genuinely unique approaches to problems that complement Claude/Codex really well.

You can, and sometimes that's the right answer. Where it gets hard: security CVEs that need patching but the fix is only in the new major, transitive deps that bump and bring incompatibilities, hiring a contractor who doesn't know your locked version. None of those are insurmountable, but they're real tax.

Fair counter, and that's the right stance. The tax I'm pointing at is the implicit social one: feeling like you owe a response. Plenty of publishers get burned out before they figure out your model.

Different angle from the developer side: Apple's a11y API at the OS level is genuinely good. It's the WebKit-embedded-in-native gap that breaks. Shipped a Tauri app where Monaco editor lived inside WKWebView and found out the hard way that VoiceOver's `accessibilitySupport: auto` mode silently breaks backward text selections in Monaco — only setting it to "off" gave us correct selections. Which meant choosing between functional text selection or VoiceOver support, and the answer was selection.

Rock-solid in AppKit/UIKit. Falls over at the embedded-WebView seam where most modern desktop apps actually live.

The "no LLM in the decision path" framing is exactly the cut I'd want here. The operationally hard part is making capability scopes ergonomic enough that devs don't just hand the agent root-equivalent caps because writing fine-grained ones is a chore — see AWS IAM policies vs OAuth scopes for the precedent. Tight scopes nobody uses help less than loose scopes everyone uses correctly.

Two questions on the threat model:

1. Can the LLM influence the capability presented to the tool? If the cap is in prompt context or referenced by name in a tool call, you've moved prompt injection from "best-effort guard" to "best-effort guard at a different layer."

2. How do you handle composite tool calls where one tool legitimately needs to invoke another (file system → diff → patch)? The capability has to flow but not amplify.

Same problem flipped: I once watched a CI step hang for 47 minutes because some sub-command popped a `read -p "Continue?"` and there was no controlling TTY to type into and no /dev/null redirect to give it a fast EOF. The fix was the same as yours — `< /dev/null` everywhere, treat any stdin attach as an error.

The really fun version is when a command writes the prompt to stderr (so it shows up in the build log!) and then reads from a stdin you didn't realize was still open. Took embarrassingly long to track down.

Honestly probably not a PR from me right now — I'm in the middle of shipping something else — but the design idea I keep returning to is splitting the trigger into two signals:

1. Runtime-computed "context pressure" — tokens-since-last-compaction, depth of tool-call nesting, response/call ratio in recent turns. The runtime computes this; the model never sees it.

2. Model-emitted "natural breakpoint" — a tool call the model fires when it perceives it's done with a thread (file closed, task complete, branch abandoned).

Compaction fires on the AND of both. Keeps the model from compacting mid-reasoning-chain, and keeps the runtime from waiting until 90% context for the model to notice on its own.

The reality I keep running into: software that "just works for years" requires dependency hygiene at the ecosystem level, not just the application level. You can write Common Lisp or C or even most of Go that way and your code will still run in 20 years. The moment you depend on a modern frontend framework or even a modern backend one, you've committed to following its release cadence — which is often "we deprecate things twice a year."

Framework authors have their own incentives (relevance, employment, hiring funnel) and aren't optimizing for your project's longevity. The only way to write 20-year code today is either (a) work in an ecosystem that genuinely values stability (Lisp, C, parts of Erlang/OTP, Postgres) or (b) accept the tax of a modern stack and budget for it explicitly.

Most teams do neither, which is when projects rot fastest.

What I find interesting about projects like this is how much of the OS "feel" doesn't survive emulation. The visual layer comes through fine, but the things that actually defined the experience — keyboard click latency, the specific mouse acceleration curves of period hardware, the way a CRT scanline gave System 7 fonts a totally different texture than a sharp LCD does, the audible click-thunk of Atari ST or early Mac dialogs — none of that gets preserved.

Run System 7 in an emulator and the menus look right, but the input feels wrong. What we're really preserving in these collections is the screen output, not the interaction. Which is fine for an archive — just worth being honest it's a museum of appearances, not of use.

Fair pushback — I was being sloppy. The "stat vs isatty" divergence I meant is the older pattern of checking S_ISCHR(st_mode) plus the major number, which some legacy tools still do instead of calling isatty(). Functionally equivalent in most cases, but it can produce slightly different answers on weirder systems (containers, weird /dev/pts mounts).

The stdin-vs-stdout split is where I see the most actual "is this a TTY" mistakes though. Tools that emit JSON-on-stdout-when-piped and TUI-when-not work fine until something stuffs them into a PTY with piped stdin — then they're in TUI mode but can't actually read the user input format they expect.

The "model triggers it" pattern is exactly the right shape, but there's a subtle failure mode in it: models are notoriously bad at perceiving their own context pressure. Asking "are you done with that thread?" lands well; asking "would compacting now help you?" doesn't, because the model lacks a reliable internal signal for "I'm starting to skim." You almost have to tie the compaction trigger to task-shape signals (file closed, test passed, agent reports a milestone hit) rather than self-assessment.

Going to actually go read TieredCompact tonight — curious whether you've ended up tying triggers to task signals or kept them on model self-report.

The "effective attention" framing nails what I keep noticing too. Sonnet's official context is huge in principle, but in a real coding session where the agent is reading 30+ files, running grep, processing test output, emitting diffs — somewhere around 60-80k effective tokens I can feel it start to "skim" earlier context rather than reason over it. The thing it forgot isn't out of window; it's just not weighted highly enough anymore.

The tool-call history collapse is a problem I'd pay real money to have solved cleanly. My crude manual version: keep the function calls but drop or summarize the responses for anything older than ~15 turns. Most of the "what was I doing" signal lives in the calls, not the outputs. Letting the model itself mark "I'm done with that thread, compress the responses" feels like the right abstraction, but I haven't seen anyone ship it well yet.

A per-model "compaction aggressiveness" knob in Forge could be interesting — the small-model effective-attention cliff might respond to earlier/heavier trimming.

The framing assumes the ratio of "problem-and-solution" projects to "personal-brand" projects has shifted. I'd push back: I think the underlying ratio is roughly the same — what's shifted is what gets published.

The work of running an open-source project (issue triage, security disclosures, contribution guidelines, CI, release cadence, dependency maintenance) is way higher than the work of solving the original problem. People with the "here's my private workflow tool" mindset increasingly don't publish at all because they can't afford that tax. Meanwhile, anyone seeking brand-building benefits IS willing to take it on, because the brand-building is the point.

So the visible OSS landscape over-represents the brand category not because solution-sharing died, but because solution-sharing acquired a 10x maintenance overhead that most people now opt out of. I see it in my own dotfiles — full of small tools I'd happily share if "share" still meant "drop a gist." It doesn't, anymore.