Writing

AI Is My Org Chart

No release team, but everything a release team guarantees: two Android apps, one developer, and checks built with AI.

8 min read

  • Android
  • CI/CD
  • Claude Code
  • DevOps
A solo developer's org chart: me at the top with AI accounts on a dotted line, and below, Release Engineering, DevOps, Infrastructure, Security, Compliance, Test Automation, QA, Design, Marketing, and Support as open headcount

I ship two Android apps by myself. Driftwell, a sleep app that plays affirmations over generated tones all night, is on Google Play. RuckPace, a pace coach for rucking, is with testers. Both are side projects under my own LLC.

A company that ships apps has whole departments for release engineering, DevOps, security, QA, design and marketing. I don’t. I have five AI subscriptions, and with them I built the part of each department’s job that one person shipping two apps can’t skip.

How to read the chart. None of these is a whole department. Each box is the slice of that job I needed, and each section ends with ideas for skills that would cover more of it. A dark chip like /fix-raw-bugs is a skill you can install. A light chip is something Claude built for my setup, so I give the prompt instead.

Release Engineering

Release Engineering: /ship-testers and /ship-production. Runs every time I ship. Stops red code, typos, double uploads and untested builds reaching production

This is the department I care most about, because it’s where a mistake reaches a stranger’s phone. Both apps ship through ship_android, one Fastlane plugin they pin by tag, so a fix to one app’s release is a fix to both. I never type the Fastlane command. /ship-testers shows me the app, the commit and the exact release notes, then asks before anything uploads.

  • Only green code ships. HEAD has to be the tip of main, and every CI check on it has to have passed. No checks is a refusal too.
  • A typo never ships. Unknown options abort first, so a misspelled dry_run can’t publish while I think I’m rehearsing.
  • Nothing uploads twice. Once Play has the build, nothing after it can fail the ship and tempt a rerun.
  • Production gets what testers had. /ship-production promotes the tagged tester build unchanged and refuses diagnostics builds and emergency bypasses. Firebase Test Lab on five phones is next, built on a branch.

Real terminal output: the RuckPace tester lane refusing a branch with an unmerged commit, offering allow_unmerged:true for an emergency build The gate refusing a real RuckPace branch, with the bypass right there in the message.

Both skills and the lane are open source:

/plugin marketplace add frictionlesscode/claude-plugins
/plugin install ship-android@frictionlesscode

DevOps

DevOps: GitHub Actions and emulator tests. Runs every PR and after every merge

Every PR runs the Android build, unit tests, lint, screenshot checks and an R8 shrink, and the Mac builds the iPhone app. After a merge, Driftwell’s emulator tests put playback through a phone call, unplugged headphones and deep power saving.

RuckPace's live screen at double font size with four layout bugs circled
Four layout bugs the screenshot checks caught at Android's largest font size. How that test works is in AI Flattened the Testing Pyramid.

If CI shares a machine with Android Studio, give the CI emulator its own port and skip the Actions cache. A self-hosted runner keeps its Gradle home, and restoring a cache over it cost 12 minutes a run.

Set up GitHub Actions for this Android app on my self-hosted runners. On every PR: build, unit
tests, lint, screenshot checks and an R8 release shrink. After a merge: emulator tests on a
port other than 5554, with ANDROID_SERIAL pinned. Don't use the Gradle Actions cache.

Infrastructure

Infrastructure: self-hosted runners on an Intel i5 Windows server, an M1 Pro MacBook and a Linux container

On GitHub-hosted runners, a couple of pull requests used up my whole month of Actions minutes in half a day. The macOS job, billed at ten times the Linux rate, was 87% of it.

One month of GitHub Actions minutes used in half a day: 87% by the macOS job

So Claude moved CI onto machines I already owned, as self-hosted runners GitHub doesn’t bill for: Windows and a Linux container on an i5 server, and macOS on an M1 MacBook it set up over SSH. Keep those repos private, because on a public repo anyone’s pull request can run code on your machine.

Move this repo's GitHub Actions jobs to self-hosted runners on machines I own. Windows jobs on
this server, Linux jobs in a Docker container here, and a macOS runner on my Mac over SSH.
Label each runner, update the workflows, and show me one green run on each.

That bill set the rule for the whole chart: nothing that runs on every change should cost money each time it runs, Actions minutes or AI tokens. Next up here: moving the runners off my user account, which today can read the release keys.

Security

Security, marked Next up: rulesets, gitleaks, Dependabot and pinned downloads, being set up now

Security is the department I’m staffing right now. None of it is live yet. The plan is to make the pipeline enforce it:

  • Nothing reaches main red, including from me: a ruleset with no admin bypass.
  • CI can’t read the release keys: runners under a locked-down user.
  • Secrets never leave the machine: gitleaks before every commit and in CI.
  • Vulnerable dependencies show up as PRs: Dependabot, grouped weekly.
  • What CI downloads is what I reviewed: Actions pinned to SHAs, downloads to checksums.

Each one gets broken on purpose once before I count it.

Lock down this repo. A ruleset that requires a PR and passing checks, with no admin bypass.
gitleaks as a pre-commit hook and as a CI job. Weekly Dependabot, grouped. Every Action pinned
to a commit SHA and the Gradle wrapper to a checksum. Then break each guard once on a branch
and show me it failing.

Compliance

Compliance: Play Store policy in CLAUDE.md and backup rules, read every Claude session

Most of the code is written with Claude, so Play Store policy lives in CLAUDE.md, where Claude reads it every session:

  • No clinical claims, in an app with affirmations for anxiety and addiction.
  • No permission without the feature that needs it, and never background location.
  • No analytics or crash SDKs, so the Data Safety form is short and true.
  • Backup rules keep the user’s affirmations out of their cloud backup.
Add a Play policy section to CLAUDE.md for this app: no medical claims, no permission without
the feature that uses it, no background location, no analytics or crash SDKs. Add backup rules
that keep the user's personal content out of their cloud backup, and prove it with a backup
and restore on the emulator.

Test Automation and QA

Test Automation and QA: screenshots on 5 setups, GPS replay tests, a QA page per change, and /fix-raw-bugs

Test automation asks whether anything broke: every screen drawn on five setups, real rucks replayed from their GPS logs, and the emulator tests. QA asks whether the build is good, which still needs a person. Claude writes a QA page per change that I work through on my phone, and /fix-raw-bugs turns tester reports into triaged fixes.

A crumbling testing pyramid next to a single flat row of tests

Every test, with its prompt, is in AI Flattened the Testing Pyramid.

Design

Design: /codex-graphic, Claude Design and Living Mocks. Runs before any code exists, and for every article graphic

Design happens before code. Claude builds Living Mocks, HTML screens made from the app’s own colors, fonts and components, so every design decision is one the app can actually build. That loop is in How Claude Can Get Product, UX and Engineering to Stop Arguing.

Article graphics go to OpenAI. /codex-graphic has Claude write the brief, hand it to the Codex CLI on my ChatGPT plan, and check every word that comes back. It made the hero, the nameplates and the Support illustration below.

Marketing

Marketing: Play Store listings, /product-video, /write-article and /medium-sync

Claude wrote both Play Store listings from the code, not from memory: descriptions, screenshots, the feature graphic, the Data Safety answers and the privacy policy. /product-video made this RuckPace tour from emulator recordings with Remotion and FFmpeg:

/write-article drafted this article, and /medium-sync cross-posts it to Medium.

Open headcount: Support

Support, with an Open HC ribbon: today it is my inbox

Support is my inbox. Hopefully ticket volume never needs an agent.

Illustration of a call centre with dozens of desks, each staffed by a small figure with a Claude spark for a head, answering calls
If it ever does.

Summary

Being a solo developer used to mean taking shortcuts, because the checks a release team runs took a team. That’s not true anymore.

A department provides guarantees: nothing ships red, no secret leaks, every release gets a real check. Scale those with people and process instead of automation, and every handoff adds a wait and someone catching up on what they missed. Those two taxes, coordination and context, grow with every person you add.

With AI building the gates once, I keep every guarantee and still make the call on what ships. Every department should look at what it can automate or hand to an agent: fewer handoffs, shorter delays, and room to scale with demand rather than headcount.