We Stopped Writing the Code

Autonomous agents sharply reduce the cost of writing native platform code, leaving human builders to concentrate on product direction and responsibility.
We Stopped Writing the Code

The software workflow has changed. We no longer spend our days writing language syntax. Our new role is to set architecture and scope the work, allowing us to judge behavior and accept responsibility for the final application. For decades, the primary constraint on software production was the physical limit of human typing combined with the mental fatigue of managing complex state transitions. When autonomous agents assumed the burden of raw implementation muscle, the economic equation of software engineering shifted. Producing the logic is no longer the bottleneck. The bottleneck is the human operator who must define the exact execution bounds and assume the ultimate blame when the machine attempts to introduce structural flaws.

This transition alters what we do when we sit at a computer. We spend our time obsessing over scope and writing exact task definitions. We correct machines when they drift from the architectural intent. They require a human operator to enforce rigid boundaries and maintain a relentless focus on product quality. If the human abdicates this oversight role, the agents will generate a distributed disaster of plausible but subtly broken logic. By accepting the role of director, we unlocked the ability to build and maintain multiple native applications simultaneously. The rote mechanics of software engineering have been commoditized. This leaves us to focus on application behavior and hardware verification.

Why cross-platform compromise was once rational

We originally chose a cross-platform framework because maintaining multiple native repositories appeared too costly for a small group. A single constrained codebase offered the illusion of efficiency. We accepted abstraction leaks and the constant friction of fighting platform conditionals because we could not afford to staff four separate engineering efforts. The decision was rational under the old constraints of manual software production. We traded native performance for a manageable maintenance burden. That trade resulted in an architecture that accumulated compromises over time, making application behavior increasingly difficult to untangle. The unified struggle proved insufficient for our goals.

Exact task scoping and repeated correction

When you remove the human from the rote mechanics of syntax production, the engineering bottleneck shifts squarely onto task definition. You cannot point a machine at a blank repository and ask for a secure messaging client. You must break the work into sharply scoped goals and keep prompting the machines until they build the exact logic you demand. The concrete method involves one human keeping several native apps moving simultaneously by writing small instructions and correcting the agents repeatedly. The machines will drift from the architectural intent. They will attempt to blur the boundaries between layers or invent unnecessary abstractions. The human operator must serve as a strict director who forces the agents to refine their output until it matches the design requirements perfectly.

You must push back on the machine, explaining exactly where the logic failed and demanding a revised implementation. This feedback loop is the new core loop of software engineering. The friction of development has moved from typing characters to reading diffs and enforcing standards. The moment your attention slips, the agents will introduce subtle technical debt that compounds over time.

A compact Marmot and MDK example

The original White Noise implementation struggled under the weight of accumulated compromises, prompting a rewrite of the Marmot protocol and its platform clients. We built a shared Rust development kit containing the group key agreement engine and a conformance simulator. By isolating the hardest state transitions into this shared core, we made client development radically simpler for the autonomous agents. The shared runtime exposes bindings to higher-level platform languages. Client repositories can focus entirely on native presentation. This compact origin story provided the template for our current method. The clear placement principles prevented boundaries from blurring during rapid agent development, proving that machines can build reliable software if given a mathematically bounded domain.

Separate native clients

Because machines sharply reduce the marginal cost of producing language-specific code, framework reuse is no longer a primary constraint. We escaped the friction of cross-platform development by replacing our unified struggle with specialized native repositories tailored to each operating system. Android is now a Kotlin and Jetpack Compose application. iOS is a distinct SwiftUI client. We built a separate macOS SwiftUI client, and we rewrote the Linux desktop client in Oden. Having separate native repositories lets each client follow the interaction models of its specific environment natively.

The platform differences are product requirements demanding respect, not wasteful duplication to be abstracted away by a heavy framework. When a machine handles the tedious translation of business logic, maintaining separate repositories becomes a manageable task. We tell the machine what the interface should expose, and the agents write the boilerplate required to connect the layers together. Producing this implementation requires tooling subscriptions costing roughly two hundred dollars a month. That price is radically cheaper than staffing several native engineering teams to build separate clients.

Giving agents physical hardware

The methodology bridges the gap between generated code and physical reality. An agent testing its own output in a mocked software environment can report success even when the resulting application is unusable in the real world. We solved this by giving the agents guarded access to an actual device. On September 9, 2026, the guarded status client reported one authorized GrapheneOS phone connected over USB. We use this as a concrete development anchor, not as a blanket release claim that every platform has identical physical automation.

The workflow permits agents to install the built APKs directly onto the physical phone through guarded wrappers. The machine can exercise UI and lifecycle behavior. It can capture finite logs and bounded Perfetto traces, diagnose failures, change code, and return another build. After a successful compilation, the machine tests the artifact on the target hardware.

We give the machine the ability to observe the physical device, but the human retains authority over the product experience. We hold the physical phones in our hands to confirm the interface responds correctly to human touch. Guarded device access lets agents diagnose and repair mechanical failures earlier while preserving human judgment. Human hands remain the final product test.

Machine review and automated testing

A skeptic will point out that generating multiple codebases can replace one localized mess with four distributed disasters. Autonomous agents can write wrong or insecure code at terrifying speed, multiplying the review load on human maintainers by flooding repositories with plausible submissions. A naive approach automates the production of technical debt and accelerates the degradation of the software suite.

We answer this threat with a rigorous method that separates direction, code generation, machine review, and automated testing. Humans must not be the exclusive code reviewers. Fatigue guarantees that machine-generated flaws will slip into production. We force agents to review diffs and run automated checks. One agent writes the implementation. A second independent agent reviews the diff for security flaws. The machines run the automated test suites before any human looks at the result. Independent machine review gives structural errors another chance to be caught. The autonomous review step is a non-negotiable requirement. By the time a build reaches the physical phone, it has survived multiple rounds of hostile machine inspection.

Human direction and accountability

The final boundary in software development remains human accountability. We use machines to generate implementation and run automated checks. They review diffs and use guarded physical-device access, but the machine cannot take the blame for the bugs. The human operator owns the final product decision. We meticulously set the architecture. We hold the hardware in our hands and make the final judgment on whether the software is worthy of release.

This shift destroys the common excuse for inaction in the open-source community. You can no longer claim that your lack of coding skill prevents you from contributing to privacy tools. If you care about censorship resistance, you have no excuse for sitting on the sidelines complaining about the software someone else built. That barrier to entry has fallen completely. Real work is waiting for someone to direct it. The community needs people who can define clear problems and assume responsibility for the final artifact. We need people who possess the tenacity to argue with a machine until the application behaves flawlessly on the target hardware.

Choose a specific platform and a specific user in need of better tools. Define one tightly bounded problem you want to solve. Use autonomous agents to implement the logic. Instruct the machines to review the code and mandate automated testing before you touch the build. Check the resulting behavior yourself on the physical device. Stop waiting for permission or massive budgets. Get your shit together and build.


Write a comment