Engineering · AI
My Daily AI Workflow in the Terminal
Mihajlo Petrović5 min read
No chat window, no magic - a concrete account of how I actually use coding agents day to day: instructions files, plan-first prompting, sub-agents, hooks, worktrees, and the things I deliberately never delegate.
I've settled into a way of working with AI that looks nothing like the demos. There's no chat window open next to my editor. Most of the interaction is in a terminal, most of it is short, and a surprising amount of it is me saying "no, not like that" before any code exists.
This is the concrete version: what I actually run, in what order, on a normal working day.
The Setup, Once
Three things live in the repo and pay for themselves every session.
The instructions file. CLAUDE.md at the repo root. Twenty-odd lines: what the project is, the folder layout, the state-management approach, the commands for test and lint, and a short list of prohibitions. It's loaded automatically every session, so I never re-explain the basics.
Permissions. Allowlist the read-only commands you run constantly — npm test, git status, git diff, ls, type-checking. Every prompt you don't answer is a small tax you stop paying. Keep anything destructive (rm, git push, migrations) behind a confirmation, permanently.
A couple of slash commands. The prompts I type more than twice a week became commands: one for "review the current diff against our conventions", one for "write tests for the changed files, behaviour not implementation". Anything I'd copy-paste from a notes file is a candidate.
The Loop
1. Plan before code — always
The first message is never "implement X". It's a version of:
Read
deposit.service.tsand how caching is used elsewhere in this repo. Propose two approaches with trade-offs. Don't write code yet.
Ninety seconds to read, one sentence to correct. Fixing a misunderstanding at the plan stage costs nothing; fixing it after 400 lines costs a review cycle and a lot of willpower.
If the plan is wrong twice, that's a signal about my prompt or the missing context — not about the model.
2. One task, one branch, commit both sides
I commit before the agent starts and after it finishes. Revert is then one command and sunk cost is genuinely zero, which is the whole economic point of cheap generation: throwing work away has to be trivially easy or you'll rationalise keeping something mediocre.
3. Delegate the reading, keep the writing
Anything shaped like "search the whole codebase and tell me one thing" goes to a sub-agent with its own context. It reads 40 files and returns a paragraph. My main session never sees the 40 files — which keeps it fast, cheap, and focused, for the reasons in the context engineering post.
4. Make it verify itself
"It should work" is not a result. The agent runs the tests. It loads the page and reads the console. It checks the types. If a change is visible in a browser, it takes a screenshot and I look at the screenshot.
This is the single biggest quality difference between people who find agents useful and people who find them exhausting. An agent that verifies is a colleague; an agent that reports success without checking is a liability.
5. Read the diff like a stranger wrote it
Because one did. My checklist hasn't changed:
- Do I understand why every non-obvious line is there?
- Does this duplicate something that already exists?
- What happens on the failure path — really?
- Would I have written something structurally similar?
If the diff is past a few hundred lines and I'm skimming, I throw it away and re-scope. Skimming is precisely how the subtly-wrong code gets merged.
Parallelism, Carefully
Git worktrees are what make running two agents at once sane: each gets its own checkout, its own branch, its own working tree, no fighting over uncommitted changes.
But two is my honest ceiling. The bottleneck isn't generation, it's my review. Three agents producing diffs faster than I can read them isn't productivity, it's a queue with a person at the end of it — and the person is the part that guarantees quality.
Hooks: Automate the Nagging
Anything you'd say more than three times should be a hook rather than a habit. Mine are boring and effective: run the formatter after any file write, run the type-checker when a .ts file changes, block edits to lockfiles.
The general principle: don't ask the model to remember your process. Enforce the process outside the model, where enforcement is deterministic.
What I Don't Use It For
Honest list, because the enthusiasm usually skips this part:
- Anything I don't understand well enough to review. If I can't judge the output, I'm not using a tool, I'm gambling.
- Architecture decisions. I'll use it as a sounding board — "argue against this design" is a genuinely great prompt — but the decision is mine to own.
- One-line changes. Typing it is faster than describing it.
- Anything touching production data. Read-only, always.
The Honest Summary
The workflow above roughly doubles my throughput on well-specified, tedious work: refactors, tests, migrations, boilerplate, reading unfamiliar code. It does approximately nothing for the hard parts — deciding what to build, choosing an architecture, knowing which edge case actually matters in a banking flow.
Which is fine. Those were always the parts I wanted to spend time on.
- #ai agents
- #workflow
- #claude code
- #developer productivity
- #git
Written by
Mihajlo Petrović
Software engineer in Belgrade. Builds his own products and the AI automations that keep them running.