My setup, and how I got here.
It didn't start as a plan. Almost every piece of it comes from something a job, a team or a bottleneck taught me, from agency work in Barcelona to leading the Experience Team at InSpace, and it still changes every week. This is how it came together, what it looks like today, who it's for and what it gets me.

Every setup is a record of the problems its owner got tired of. Mine is no different. The window manager, the scripts and the agents are each there because, at some point in some job, I lost time, quality or focus to the thing they now handle.
So instead of opening with a list of tools, I'll start with the story. The tour comes after, for anyone who wants to borrow something.
01 — 2019 · BarcelonaOwn the whole path
My first job in software came right after a web development bootcamp at Ironhack. I joined Nakima in Barcelona as a fullstack developer, and it was agency work at its busiest: web apps in React and Angular, mobile apps in React Native, backends on Firebase and MongoDB, and one project that ran facial recognition on the device itself.
What stayed with me had little to do with frameworks. I owned client requirements from start to finish (scoping, delivery, the next iteration), and I was often the person translating between designers, the backend team and the client. Two lessons came out of that. First, the job isn't writing code, it's shortening the distance between someone's problem and a working solution. Second, switching context is expensive. Every time you jump between projects you pay a re-entry cost, and nobody budgets for it.
02 — 2021 · RemoteTrust comes from tests
In 2021 I joined finsit, part of Wolters Kluwer, working remotely. I built frontend modules on top of internal libraries, contributed to C# services, and spent a lot of my time making critical flows dependable with Cypress and Jasmine. I also modernised shared components and tooling, and that sped up the whole frontend team more than any single feature I shipped.
That's where I grew from junior into someone the team relied on for critical processes. It's also where I learned that you can only hand work to someone else when tests and clear writing define what "correct" means. That someone might be a teammate, a new hire or, as it turned out, an agent. The other lesson was that shared tooling is some of the highest-leverage code you can write.
03 — 2024 · EindhovenPipelines over heroics
At YieldComputer, from 2024 to mid-2026, I automated the release pipeline, defined a testing strategy across unit, integration and end-to-end tests, and introduced product analytics so we could prioritise from evidence instead of opinion. The results are on my homepage, but the lesson is simpler: teams don't get fast by working harder. They get fast when shipping is safe and boring, and when that safety lives in the pipeline instead of in someone's memory.
It's also where I learned to lead without formal authority. You find the bottleneck, build something that removes it, and make it easy for people to adopt. Then you look for the next bottleneck.
04 — 2026 · InSpaceMake it effortless
On 1 July I left YieldComputer and joined InSpace. InSpace builds NOVA, an autonomous AI platform for SEO and GEO (generative engine optimisation). It researches, writes, optimises and publishes the content that gets brands found, both on Google and in the answers of ChatGPT, Gemini, Perplexity and Claude.
As a senior engineer, I lead the Experience Team. We build the platform our clients see and use every day, from their dashboards to the moment they approve a page. Interfaces that feel effortless take precision and taste. Much of my work is building components and patterns that scale across NOVA, keeping the whole product consistent as it grows.
I also try never to stop at "does it work?" I want to know who's using it, what they're trying to achieve, and what the interface is really asking of them. That's why I'm as comfortable in a product conversation as in a pull request.
NOVA's promise to clients is "AI does the work. You make the call." Nothing ships without the client's yes, and every correction teaches NOVA, so it needs less checking next time. That turns out to be a pretty good description of how I build it, too.
05 — 2026 · The workflowEnter the agents
Claude had been my daily co-pilot for a while, for pairing on architecture, drafting and refactoring. A new team, a new codebase and a product that is itself built on AI changed the question from "can it help me write this?" to "can it take this ticket, and can I trust what comes back?" Answering it took everything from the chapters above, and it didn't happen in one go:
- JuneMake the base reproducible. Before my first day at InSpace, I turned the machine itself into code: one command rebuilds my Mac.
- JulyOne task, one worktree. In my first weeks on the team: first a script that gives every task its own worktree and dev server. Then a cockpit that sends each task to its own tab and agent session, and a monitor that shows which ones are waiting on me.
- AugustPast the pull request. The bottleneck moved to CI and review. A loop now watches every PR and sends failures and comments back to the session that wrote the code. Complex work gets a cold second review, and real review comments became checklists that every future task reads.
- SeptemberRespect the machine. With many sessions on one laptop, builds started fighting over the cores, so expensive commands now queue for a slot. Small fixes were going through the heavyweight process, so how deep a task goes now depends on how complex it is. The menu bar learned about meetings.
- This weekReview gets its own tools. A PR opens as a staged diff in lazygit, Claude's first pass lands in my pending review, and one key jumps from a PR to the session that wrote it.
None of this was planned up front. Each step dealt with the bottleneck the previous one exposed. That's the same loop I used to run with teams, only now some of the team is software.
06 — The tourThe setup today
Here's where it stands this month, from the bottom up.
The machine
A MacBook Pro, usually docked to an ultrawide monitor. Everything runs on that one laptop, including every agent session, and it's configured entirely from mac-setup, a public repo:
$ bash <(curl -fsSL https://raw.githubusercontent.com/birrejan/mac-setup/main/bootstrap.sh) # preflight → homebrew → dotfiles → languages → git → ssh # → vscode → iterm2 → wm → macos → touchid → doctor ✓ every step is idempotent, and re-runnable alone with --only <step>
A Brewfile lists every tool, app and font. GNU Stow symlinks the dotfiles, so editing a config means editing the repo. doctor checks the result, and dump.sh syncs back anything that isn't a symlink. It also handles the dull but important bits: SSH-signed commits, Touch ID for sudo and sensible macOS defaults.
The desktop
AeroSpace tiles every window, so nothing overlaps and I move around with ⌥ hjkl. Some workspaces have a fixed job (chat, calendar, email), apps are routed to them automatically, and switching to one that's empty opens its apps. JankyBorders outlines the focused window, since tiled windows have no title bar to tell you where your keystrokes will go.
The menu bar is SketchyBar, extended with a small native Swift helper:
- Machine load at a glance. CPU and memory cards stay out of the way until the machine is busy, then turn amber, then red. With agents building in the background, this is my early warning.
- Meetings that don't sneak up. A pill appears half an hour before a call, joins it in one click and can start a Granola recording. It reads my calendars and never writes to them.
- Screen-share safe. Presentation mode hides app, media and meeting titles. A mic/camera card lights up only while either is live.
- Display-aware. It works around the laptop's notch and switches layout profiles when I dock or undock.
The terminal
iTerm2, zsh with no framework, Starship for the prompt, mise and uv for runtimes, and modern replacements for the classics: eza, bat, ripgrep, fd, zoxide, fzf. My pull-request queue lives in gh-dash, grouped by what needs doing (CI failing, changes requested, ready to merge, needs my review), with a few keybindings I added:
| i | Review in lazygitThe PR is checked out into a throwaway worktree and shown as one staged diff. I leave line comments in a pending GitHub review without touching my own checkout. |
| I | Claude reviews firstA fresh-context agent reviews the PR and puts its findings into my pending review. Nobody sees anything until I've edited it and submitted. |
| T | Jump to the taskFocus the agent session that wrote this PR. |
The agents
~/Projects is a cockpit for NOVA's codebases: the app, its design system and the services around it. A Claude Code session started there doesn't write feature code: it starts tasks, tracks them and gets them merged. I describe the work, and the cockpit builds an isolated worktree from the latest base branch, registers the task and opens a new tab with a pre-briefed session. Every task starts read-only, in plan mode, and works through the same pipeline:
- Ticket
- Definition of Done
- Clarify
- Plan
- Implement + tests
- Gate
- Self-review
- Verify in the app
- Draft PR
- Second review
- Ping me
How deep a task goes depends on a complexity tier. A typo fix gets a plan of a few lines that I can approve at a glance. Standard work gets a fuller plan and a full self-review. Complex work also gets an independent second review: a fresh agent sees only the PR and the checklist, never the author's reasoning, and reviews it cold.
Once a PR is open, a loop in the cockpit watches CI and review comments and sends anything actionable back to the session that wrote the code. When a human review comment applies more widely, it's added to that repo's review checklist, which every future task reads while coding and again at self-review. For example:
“Fail-open guards: never discard the error from a query used as a guard. A read error must fail the action, not let the write proceed.”
A lesson written there is a review comment no future PR needs. Around all of this, clorch shows which sessions are working, idle or waiting on me. A shared slot pool makes expensive builds and test runs queue instead of competing, so the laptop stays responsive while many tasks are in flight.
07 — Professional defaultsGuardrails I don't bend
Speed only counts if you can stand behind what ships. These rules hold for every task, whatever its size:
- Plans before code.Every task starts read-only, in plan mode, and nothing changes until I've approved its plan. For a small fix that plan is a few lines, so approving it takes a glance.
- Isolation by default.Each task has its own branch, worktree and environment. Nothing touches my main checkout, and nothing touches another task.
- Evidence, not claims.A PR carries its Definition of Done, test output, a self-review summary and proof from the running app. "Done" is something you can check.
- A human reviews every diff.Agents open drafts. I review, my teammates review, and people decide what merges.
- Lessons get written down.Review feedback becomes a checklist, so the same comment never has to be made twice.
- The machine is a shared resource.Expensive work queues for a slot rather than grinding the laptop for everyone, me included.
08 — People & fitWho it's for
First, who does what. The setup only works because the split is explicit:
Me
Decide what's worth building, shape the ticket, approve plans, review every diff, merge.The agents
Turn tickets into tested, verified draft PRs, fix red CI and respond to review comments.My team
The Experience Team and the wider engineering team review and approve, like always. Agents open drafts; people decide what ships.And who should copy it:
- Product engineers with a steady stream of well-scoped features and bugs.
- People who already review more code than they write, and are fine with that.
- Anyone who likes owning their tools. It's all plain scripts, JSON and markdown you can read and change.
- Exploratory work where you don't know what you want yet. Agents amplify clarity; they don't create it.
- Anyone who won't read the diffs. The whole system assumes a human reviews everything.
- Teams without CI or tests. The gates are what make handing work off safe.
09 — Benefits & trade-offsWhat it buys me
- More in flight, less in my head. Several tasks move in parallel, and each one keeps its own context, so picking one up again is T, not ten minutes of rereading.
- Time back for the product work. More of my day goes to deciding, shaping tickets, reviewing and talking to people: the parts of the job I think matter most.
- Quality that compounds. Checklists and cold reviews mean the same mistake isn't made twice, by me or by an agent.
- Reproducible by default. One command rebuilds the Mac, and every config change lands in a repo as I make it.
- Focus. The desktop gets out of the way. Load, meetings and the PR queue are visible without going looking for them.
The honest trade-offs
- The bottleneck moves to review. Reviewing well is most of the job now, which is why review has its own tooling.
- Agents are only as good as the ticket. Vague in, vague out. That's why every task starts by writing a Definition of Done.
- It's my own glue. Shell scripts, skills and config. That's powerful, but when something breaks, I'm the maintainer.
- Compute and tokens aren't free. That's why depth scales with complexity, and heavy multi-agent work is kept for the few tasks that need it.
10 — Always iteratingNever finished
This setup is never done, and I've stopped wanting it to be. It changes on two rhythms:
What makes that sustainable is the same discipline I'd expect from any production system. Everything lives in versioned files. Decisions sit next to the config they explain. And a change doesn't count until it's written down somewhere the next task, or the next version of me, will read it.
Next month, parts of this post will be out of date. That's the point.
Standing on shoulders
- AeroSpacetiling window manager
- SketchyBarthe menu bar
- JankyBordersfocus outline
- gh-dashPR dashboard
- lazygitgit & review UI
- clorchagent session monitor
- Claude Codethe agents
- Starship & miseprompt & runtimes
If you want to take something, start with mac-setup. It's public and it's meant to be forked. If you're building your own agent workflow, I'd love to compare notes.
What's in your setup?
Questions, pushback or your own take? I read every email.


