AI coding agents: seven habits that work and two I dropped
I use AI coding agents for most of my work: Claude Code, OpenAI’s Codex, and OpenCode. They run on my Mac, a Linux desktop, and a research server (a rented VPS, or virtual private server), often for hours at a time. Over a few months, some setup choices kept paying off and others did not. This post covers seven habits I keep and two I removed, with the evidence for each.
| Area | Habit |
|---|---|
| Usage limits | Open Claude’s 5-hour window early; use the extra pools: OpenAI’s dot and monthly API credits |
| Output | Agents write into a synced Obsidian vault |
| Shared context | One instruction folder for every agent; pull before every session; trail notes |
| Safety | A limited GitHub account for unattended agents, and a backup they cannot reach |
Start the 5-hour window before you wake up
A Claude subscription limits usage in two ways: a weekly cap, and a session window. The session window lasts 5 hours. It starts with the first message you send, and when it ends, your next message starts a new one (Anthropic’s help article). The window does not reset at a fixed hour. It follows you.
So the start time of your first window decides where every reset falls for the rest of the day. I do not want that to depend on when I first open my laptop. I set up a scheduled task in the Claude app that sends one tiny prompt every morning at 8:00 with Haiku, the smallest and cheapest model:

The prompt is “just say ‘hi’ to me, no need to do anything else”, and the answer is “Hi! 👋”. It costs almost nothing, but it opens the window. The run list shows it firing every day between 8:02 and 8:09.
Here is why the start time matters. Let $s$ be the hour of the first message of the day, and $b$ the hour my working day ends. If I keep working, window $k$ (counting from $k = 0$) runs from $s + 5k$ to $s + 5(k+1)$, and a new one opens at each reset. The number of windows that open before $b$ is
$$ N(s) = \left\lceil \frac{b - s}{5} \right\rceil, $$where $\lceil x \rceil$ means $x$ rounded up. If my first real message is at 9:00 and I stop at midnight, $N(9) = \lceil 15/5 \rceil = 3$. With the 8:00 ping, $N(8) = \lceil 16/5 \rceil = \lceil 3.2 \rceil = 4$.

The chart shows both days. The fourth window only helps on a late night, but the shift helps every day. If I use up a window by late morning, the reset comes at 13:00 instead of 14:00. Each later reset also comes one hour sooner. On a busy day, the first window has been open for an hour before I start, and I still get its full budget.
Two limits apply. The weekly cap does not change, so more windows give more room on heavy days, not more usage per week. And this only helps if you actually use Claude in the morning. If you start at noon, schedule the ping for 10:00 or 11:00.
Use the extra pools: OpenAI’s dot and monthly API credits
A subscription now comes with more than its chat limits. Two extra pools are easy to miss.
OpenAI’s dot. OpenAI launched dots at DevDay on 2026-09-29: an always-on personal assistant that works in the background toward a goal you give it. It comes with ChatGPT Pro, and chatting with it does not count toward ChatGPT’s usage limits. In my experience it is also good: research, reading and planning, the kind of work that would otherwise eat into my Claude and Codex limits.
The limit is generous, but it exists. After a heavy stretch, my dot answered a status question with “Your dot is on a break”, and told me I had hit its “abuse prevention limit”. It came back after a while. So I treat dot as a large extra pool for non-coding work, not as an unlimited one, and I keep coding in Claude Code and Codex.
Monthly API credits. In October 2026, Anthropic and OpenAI both started adding API credit to their top subscriptions, worth about the price of the plan (Anthropic, OpenAI). API credit pays for code that calls the model directly, outside the chat apps:
| Plan | Monthly API credit | What it does not cover |
|---|---|---|
| Claude Max | $100 | Interactive Claude Code, extra usage in the Claude apps |
| Claude Ultra | $200 | Interactive Claude Code, extra usage in the Claude apps |
| ChatGPT Pro | $100, $200 or $500, matching the tier | Codex, ChatGPT usage |
To claim it, you link the subscription to an API account you own, once the plan is seven days old. Unused credit expires at the end of each billing cycle; nothing rolls over. So the credit suits work that is not an interactive coding session: the Agent SDK, scripts that classify or summarize data, and recurring batch jobs in a research pipeline. That work would otherwise come out of the chat limits or need a separate API bill. Because the credit disappears each month, recurring batch work is the first thing to point at it.
Let agents write into Obsidian, synced by Syncthing, backed up by Git
Agents produce a lot of output: reports, findings, decisions. If it stays in a terminal or a chat log, I never read it again. So every substantial task ends with a report in my Obsidian vault, the note app I already read every day.

The left half of the diagram shows the vault. Two tools do two different jobs:
- Syncthing copies files between my Mac and the server within seconds, with no cloud service in between. An agent on the server writes a report, and it is on my Mac before I switch windows.
- Git keeps the history. Each machine has its own clone and pushes to a private GitHub repository. Syncthing spreads every change at once, deletions included, so a mistake on one machine reaches the other right away. Only a commit can bring a file back.
Two rules keep this safe. First, agents write only in their own folders (projects/ and sources/); my personal notes are read-only to them unless I ask. Second, an agent commits before it pulls. Syncthing-copied edits look like local changes to Git, so pulling first fails.
One folder of instructions for every agent
Each agent reads its own instruction file: Claude Code, Codex and OpenCode each look in a different place. I used to keep three copies, and they drifted apart within a week.
Now there is one Git repository, skills-shared. It holds instructions/AGENTS.md (how I want agents to work: style, safety limits, project layout) and myskills/ (reusable skills, such as the one that writes this blog). The right half of the diagram shows the links:
- Claude Code reads
~/.claude/rules/AGENTS.mdand~/.claude/skills. - Codex reads
~/.codex/AGENTS.mdand~/.codex/skills. - OpenCode reads
~/.config/opencode/AGENTS.mdand itsskillsfolder.
Each of those paths is a symbolic link: a small file that says “the real file is over there”. When I change a rule, every agent reads the new version in its next session. Git carries the change to my other machines.
Why not hard links? A hard link is a second name for the same file data, which sounds even better. But when git pull updates a file, Git writes a new file and swaps it into place. The hard link still points at the old data, so the agent quietly keeps reading the old rules. Hard links also cannot point at folders, and the skills live in a folder. Symbolic links avoid both problems.
Pull before every session
Agents on three machines commit and push to the same repositories. An agent that starts on an old copy of the code redoes finished work or ends in a merge conflict. So Claude Code runs a hook when each session starts. A hook is a command the app runs on its own at a set moment, whatever the agent decides. Mine runs this in the project folder:
git pull --ff-only >&2 || true
Each part has a job:
--ff-onlyonly moves my copy forward to the remote version. If both sides have changed, it does nothing, instead of making a merge commit nobody asked for.>&2sends Git’s output to the log. A session-start hook’s normal output is added to the agent’s context, and the agent does not need to read a list of pulled files.|| truemeans a failed pull (no network, or a folder that is not a Git repository) never blocks the session.
An instruction like “pull before you start” works most of the time. A hook works every time.
Leave notes for the next agent
Every agent session starts with no memory of the last one. If an approach failed yesterday, today’s agent will happily try it again. So every project has a TRAIL_NOTES.md at its root. Agents read it before they work and add short, dated entries in six sections:
| Section | What goes in |
|---|---|
| Decisions | What was chosen over what, and why, so settled choices are not reopened |
| Assumptions | What the work relies on but nobody has checked yet, and how to check it |
| Gotchas | Traps in data sources, APIs and tools that hurt even a correct approach |
| Failed approaches | What was tried, why it failed, and whether it was disproved or only abandoned |
| Open blockers | What blocks the work, what was tried, and the next check |
| Untried ideas | Good ideas nobody has acted on yet, with a rough cost |
Just as important is what stays out: to-do lists, run history (Git has it), results (they go to Obsidian), and architecture notes (agents can read the code). The file only holds what the code cannot tell an agent.
Two real entries show the idea. My note on Headroom, a tool covered later in this post, ends with “do not reinstall it without new evidence”, so no future agent suggests it again as a token saver. And while I edited this blog today, an agent retitled a post and its web address changed, because this site builds addresses from titles. It wrote that down as a gotcha, with the fix (add a redirect from the old address). The next agent that retitles a post will read it first.
Give unattended agents less power, and keep a backup they cannot reach
Agents on the server run for hours while I am not watching. A confused agent with my full GitHub login could delete a repository or make a private one public. So the server never logs in as me.
My repositories live in a GitHub organization. The server is logged in as a second GitHub account that is only a member of that organization, not an owner. On most repositories it has the “maintain” role: it can push code and manage issues, but it cannot delete the repository, make it public, or change who has access. My main account, which owns everything, only logs in on machines where I am sitting.
Check what the account can really do, though. While writing this post, I listed the second account’s role on every repository. It was “admin” on 46 of the organization’s 83 repositories, most likely because GitHub makes a member admin of every repository they create, and agents on the server create repositories. The organization also allowed members to delete repositories they administer. So an agent on the server could have deleted those 46. The fix is two switches under the organization’s member privileges: stop members from deleting or transferring repositories, and stop them from changing visibility.
The second line of defense is a backup outside GitHub. Every Sunday at 03:00, a scheduled job on GitLab’s own servers copies every repository from both of my GitHub accounts into a private GitLab group:
| Event on GitHub | What happens on GitLab |
|---|---|
| New commits | Copied |
| Branch or repository deleted | Kept; nothing on GitLab is ever deleted |
| History rewritten by a force push | The old version is kept as a separate branch, then updated |
| GitHub down or account locked | Every copy stays; clone it without any GitHub login |
The job reads GitHub with read-only tokens and runs on GitLab, not on my machines. It is not a true air gap, which would mean no network link at all. But it works like one for agents: nothing they can do with their GitHub access can delete or rewrite the GitLab copy. On the Codex side, a small hook adds one more guard. It stops force pushes and remote branch deletions that would otherwise slip past Codex’s review rules.
What did not work
Headroom: about 1% fewer tokens, at a real cost
Headroom is a local proxy, a small server between the agent and the model provider. It shortens what the agent sends, mostly long tool output, and its project page promises 20% fewer tokens for coding agents. I ran it on three machines for about a month. Before removing it, I read its own logs:
| Machine | Codex input tokens removed | Claude Code traffic through it | Cost of running it |
|---|---|---|---|
| Research server | 3.1% | 0.4% of requests | 2–3 GB of memory, 0.34 s per request |
| Linux desktop | about 1% | 5 requests in 30 days | Docker container, about 0.5 s per request |
| Mac | 0.74% | 5 requests | about 1.5 GB of memory |
That is 1–3%, not 20%. The savings were small because of the prompt cache. An agent resends its whole conversation on every turn. The provider caches the start of that conversation and charges about a tenth of the price to read it again. On my machines, 96–97% of Codex input came from that cache. Headroom must leave the cached part alone, or the cache breaks and costs go up. So it can only shorten the small new part at the end.
A worked example with my desktop’s numbers, per 100,000 input tokens: 97,400 come from the cache and 2,600 are new. If Headroom cuts the new part by 30%, it removes 780 tokens, which is 0.8% of the input. Long sessions saved the least, and long sessions used almost all the tokens.
Its dashboard said “$1,210 saved”. That prices the tokens at pay-per-token rates, but I pay a flat subscription, so my bill did not change. The real gain was a little more room under the usage limit, about 2% at best.
The costs were real, though. If the proxy stopped, every agent that used it lost its connection to the model. The Claude desktop app sets its own address and skipped the proxy completely, so 99.6% of my Claude Code traffic never went through it. And it may have made the agents worse. It shortened tool output, my own messages, and long lists (cut to 15 items). It offered a tool to fetch the full text back, but on the server, agents used it zero times in 33,730 compressions. Either the agents never needed the missing text, or they never noticed it was missing. I cannot tell which, and I do not want an agent that guesses. I removed Headroom from all three machines on 2026-11-07.
A second model to rewrite Claude’s replies
In August 2026, Opus 5’s chat replies were long and full of jargon. So I added a rule to Claude Code’s instructions: before sending any reply, Claude had to save its draft to a file, pass it to Codex running GPT-5.6 Luna with a “shorter, plainer, keep all code and numbers” prompt, and send back only Luna’s version. Luna had to start its output with the line “rewritten by gpt 5.6 Luna”. Claude was not allowed to type that line itself, so the line proved the rewrite had really happened. The same rule sent every document Claude wrote through Luna as well.
It worked, but every reply now needed two models, two waits, and some of the Codex usage limit. It also added a game of telephone: the model that did the work was not the model that explained it. With Opus 5.5, Claude’s own writing became clear and short enough that the extra pass was no longer worth it, so I removed the rule. The better fix was plain-language rules in the shared instructions file (see “One folder of instructions for every agent” above), which every agent now follows.
Takeaways
- Usage limits that follow your first message can be shaped. A free, scheduled “hi” is the cheapest fix I have found. A second provider’s assistant, such as dot, adds a separate pool for work that is not code, and the monthly API credits pay for scripts and batch jobs.
- Put agent output where you already read, and keep two copies of it with different jobs: one that syncs fast and one that remembers.
- Keep one source for instructions and link it into each agent. Use symbolic links, not hard links, when Git manages the source.
- Use hooks for rules that must always hold, such as pulling the latest code before a session starts.
- Write failed approaches down, or the next agent will try them again.
- Give unattended agents the smallest access that works, then check what that access really allows. Keep one backup their credentials cannot touch.
- Before you add a tool that saves tokens, check how much of your input is already cached. If it is above 90%, there is little left to save.
- Workarounds for a weak model age fast. Check them again with every new model.
