
- ClaudeCode
- AI
- automation
- Bash
- Python
Introduction: The cost limit guard had never once been triggered
Our company (Godo Kaisha Join Class, where I am the sole employee) runs `claude -p` unattended from scheduled launchd jobs to organize departmental status, supplement article ideas, collect leads, and perform similar tasks.
We had also set up a system with a monthly limit of $200 that would send a warning to Slack at $160. I had felt reassured, but when I checked its internals on September 25, 2026, the guard had never once been triggered.
The cause was simple: the cost-recording function merely added the “approximate value passed by the caller.” The morning digest script always passed a fixed 0.02. In other words, it was checking the limit against a fictitious number.
In this article, I will first explain how we made actual measurement possible, and then introduce the five areas we trimmed while measuring actual usage, together with the code that is actually running.
Prerequisite: Stop using estimates and record total_cost_usd
When you run `claude --output-format json`, the response JSON contains `total_cost_usd` and `usage`. Simply totaling these values gives you actual measurements.
Our implementation consists of two files. First, the wrapper:
The point is that only the response text is streamed to standard output. Since all you need to do is replace the existing RESULT=$(claude -p "...") with RESULT=$(claude_run label -p "..."), we were able to migrate the dozen-odd scripts all at once.
Next is the part that receives the JSON and records it (only the key points are excerpted).
Limiting the data retained for each job to cache_creation_tokens worked. The actual stored data looks like this (excerpt as of November 10, 2026).
Pitfalls
- Debug by removing 2>/dev/null: Errors such as an expired login are output to stderr. Immediately after the migration, remove it and run the command manually once.
- Do not use --bare: We tried it to make startup lighter, but it failed with "Not logged in" because it did not read the authentication information.
- Pass through non-JSON output as-is: If you do not ensure that the response is not discarded when parsing fails, subsequent processing will run with an empty string.
What we learned from measuring: the fixed cost per call is high
The first thing that surprised us when we started measuring was thatsimply asking "What is 2+2?" cost $0.27–0.47 per call.
Looking at the breakdown, cache creation was about 41,000 tokens. Of that, our own files (CLAUDE.md, agent definitions, and skills) accounted for only about 5,800 tokens. The rest is fixed overhead on the Claude Code side.
In other words, the idea that "all you need to do is shorten CLAUDE.md" has only a limited effect, whilewhat really matters is the number of calls and what you have it do in each call. The following five areas have been trimmed based on that premise.
The five areas we trimmed
1. Set routine jobs to --effort low
Routine work such as summarizing the status of each department does not require deep reasoning.
In our case, only one job that does not have --effort low specified remains, and comparing them shows a difference.
| Job | effort | Per run |
|---|---|---|
| dept-dev | low | about $0.35 |
| dept-sales | low | about $0.32 |
| sme-concerns | not specified | about $0.63 |
Since the contents of the prompts differ, this is not a pure comparison. That said, the cache-creation tokens are also about 1.7 times higher, and there are signs that tool calls have increased and the number of round trips has grown. The verification method is simple: run the same job several times with and without --effort low, and compare jobs.<label>.usd / calls.The verification method is simple: run the same job several times each with and without --effort low, and compare jobs.<label>.usd / calls.
2. Narrow down the tools for each stage with --allowedTools
Article topic replenishment (replenish) is the job with the most calls. We are splitting the tools that are passed between the research stage and the writing stage.
When a “search just to be safe” begins while writing, the search results go straight into the context, increasing the token count. Without tools, it cannot take a detour. From a security standpoint, it is also good not to grant unnecessary permissions during unattended execution.
3. Stop a runaway execution with --max-budget-usd 3
The --max-budget-usd 3 set in the wrapper is the maximum amount that can be used in a single execution. With unattended jobs, the frightening thing is not the average, but a single run caught in a loop. With only a monthly cap guard, by the time you notice, a full day’s budget has been spent.
The value is set at more than five times the usual per-run cost ($0.3–$0.6). If it is set too tight, a different kind of incident occurs: normal processing is cut off midway, leaving the article only half-written.
4. Check the monthly limit before execution
Merely recording the figures does not stop anything. At the beginning of each script, check the actual measured value and stop if the limit is exceeded.
The function itself had been there all along. The only thing that changed was that the numbers it reads are now real. The "guard wasn't working" issue I wrote about initially has finally been resolved here.
5. Reduce the call count itself
If the fixed cost is approximately 41,000 tokens per call, combining 10 calls into one is the most effective approach. At our company, we reviewed this in the following order.
- Sort jobs in descending order of usd
- For the top jobs, check whether they "need to be called every time" and whether they "are not being called even though the inputs have not changed since the previous run"
- If nothing has changed, finish without calling claude
This is the only command needed to display the top entries.
In November, replenish (25 calls, approximately $12) accounted for 40% of our total. This is where we will make the next change.
Results
The actual monthly figures are as follows.
| Month | Measured total | Notes |
|---|---|---|
| 2026-09 | $26.41 | Measurement began on 9/25 (about 6 days’ worth) |
| 2026-10 | $128.96 | Measured for a full month |
| 2026-11 | $30.35 | As of the 10th |
To be honest, September had a short measurement period, so I could not make a clean comparison “before trimming.” Even so, compared with $128.96 in October, November was at $30.35 as of the 10th (around $90 per month at this pace). Above all, the biggest achievement was that the $160 warning and $200 cutoff guards began working with actual figures.
Summary: Tasks for Today
- Change claude -p to --output-format json and record total_cost_usd for each job
- After collecting data for a week, look at jobs with the highest usd values
- For routine jobs, use --effort low and restrict --allowedTools for each task
- Use --max-budget-usd to set a per-run limit and check_cost_limit to set a monthly limit
- Finally, reduce the number of calls themselves
The order matters. Trimming CLAUDE.md before measuring had only a slightly more than 10% overall effect in our company.
From a management perspective, what is frightening about AI costs is not that they are high, but that they are unknown. When you can see the numbers, you can make decisions. Through this work, I once again realized that “costs can become one-tenth, but revenue does not become ten times.” I am redirecting the saved money and time to work that directly contributes to revenue.
Recommended Books
I am writing a book that systematically covers the design of CLAUDE.md, configuration, and cost management.
- 『CLAUDE.md Design Patterns』
- For unattended execution with launchd / cron, see 『The Complete Guide to Automating Claude Code』
Book list: https://zenn.dev/joinclass?tab=books
Go to list of users who liked
Go to list of comments
Register as a new user and use Qiita more conveniently
- You get articles that match your needs
- You can efficiently read back useful information
- You can use dark theme