Claude Code

Building your first Claude Code agent: an Australian small business case study

Step-by-step build of a real agent that audits a Shopify store nightly, flags inventory issues and posts to Slack. Full config + prompts.

In short

We’ll build a real agent that runs nightly on a server, audits a Shopify store’s inventory, and posts findings to Slack. Full config + cron + permissions. Total setup time: ~90 minutes. Monthly run cost: under $10 AUD.

Most “first agent” tutorials are toys. This one is the agent we actually run for an Australian Shopify skincare brand every night at 23:00 AEST. It pulls inventory state from Shopify, runs sanity checks (stock at zero, prices changed, products with no image), and posts a summary to a Slack channel.

End-to-end build below. You can adapt this template to any nightly-audit workflow.

What the agent does

Every night at 23:00 AEST:

  1. Connects to the Shopify Admin API via MCP
  2. Pulls every product + inventory level (cached from Shopify, fast)
  3. Runs three checks:
  • Products with stock at zero or below
  • Products with no image
  • Products whose price changed in the last 24 hours
  1. Posts a summary to Slack channel #overnight-inventory
  2. If anything urgent (stock zero for a top-10 SKU), DMs the operations lead

If the run is clean, it posts a one-line “All clear” so we know it ran. If it failed entirely (Shopify down, Anthropic API hiccup), we get a separate alert via UptimeRobot watching the Hetzner-side log file.

Prerequisites

  • Claude Code installed (we run on a Hetzner Ubuntu 24.04 VPS, same as our Telegram bot)
  • Anthropic API key with at least $20 USD credit and a budget alert at $40
  • Shopify custom app with read scopes for products, orders, inventory
  • A Slack incoming webhook URL
  • 90 minutes

Step 1: directory + Claude config

mkdir -p /opt/agents/skincare-inventory
cd /opt/agents/skincare-inventory

CLAUDE.md:

# Agent: nightly inventory audit

You are an unattended agent. You run once at 23:00 AEST every night.
You have no human in the loop. Speak in clear, concise prose suitable for Slack.

## Mission
1. Pull the client's current inventory state via Shopify MCP.
2. Run the three checks defined in checks.md.
3. Post a Slack summary via the slack_webhook tool.
4. Exit cleanly.

## Constraints
- Australian English.
- AUD pricing.
- Do not make changes to Shopify (read-only).
- If you cannot reach Shopify or Slack, write the error to error.log and exit 1.
- Do not call any tool more than 3 times for the same purpose.

## Output format
Slack message:
**🌙 client overnight audit, DD/MM/YYYY**
- Out of stock: <list of SKUs or "none">
- No image: <list or "none">
- Price changed in last 24h: <list with old → new or "none">

End with "All checks complete." or "Issues found, investigate."

checks.md:

# Inventory audit checks

## Check 1: Out of stock
For every product in the store, find any variant where inventory_quantity <= 0 AND track_inventory is true. List SKU + product title.

## Check 2: No image
For every active product, check that images.length > 0. List any with zero images.

## Check 3: Price changed
For every product, compare current price to the price recorded in shopify-prices-yesterday.json (created by the previous run). List any that changed, with the previous and new price in AUD.

After audit, write today's prices to shopify-prices-today.json (the wrapper script renames it to -yesterday.json).

Step 2: MCP config

.mcp.json:

{
 "mcpServers": {
 "shopify": {
 "command": "npx",
 "args": ["-y", "@shopify/mcp-server-storefront@latest"],
 "env": {
 "SHOPIFY_STORE_DOMAIN": "your-store.myshopify.com",
 "SHOPIFY_ACCESS_TOKEN": "shpat_REDACTED"
 }
 },
 "slack": {
 "command": "npx",
 "args": ["-y", "@modelcontextprotocol/server-slack-webhook"],
 "env": {
 "SLACK_WEBHOOK_URL": "https://hooks.slack.com/services/..."
 }
 }
 }
}

Step 3: settings + permissions

.claude/settings.json:

{
 "permissions": {
 "allow": [
 "mcp:shopify:*",
 "mcp:slack:post",
 "Read",
 "Write(*.json)",
 "Bash(date:*)"
 ],
 "deny": [
 "Bash(rm:*)",
 "Bash(curl:*)",
 "WebFetch"
 ]
 }
}

Only the tools the agent needs. Explicit deny on dangerous shell commands and on WebFetch (everything goes through MCP).

Step 4: the wrapper script

run.sh:

#!/usr/bin/env bash
set -euo pipefail
cd /opt/agents/skincare-inventory

# Rotate prices file (today → yesterday) for the next run's diff
[ -f shopify-prices-today.json ] && mv shopify-prices-today.json shopify-prices-yesterday.json

# Cap turns + tokens to prevent runaway
export ANTHROPIC_MAX_TOKENS=120000

# Run headless. --print exits after one cycle of agentic work.
claude --print --max-turns 25 "$(cat <<'EOF'
Run the nightly inventory audit per CLAUDE.md. Use the checks defined in checks.md.
Post the result to Slack. Write today's prices to shopify-prices-today.json.
EOF
)" > last-run.log 2>&1 || {
 echo "Inventory audit failed at $(date)" >> error.log
 curl -s -X POST $SLACK_WEBHOOK_URL -H 'Content-Type: application/json' \
 -d '{"text":"⚠️ the nightly inventory audit FAILED, check /opt/agents/skincare-inventory/error.log"}'
 exit 1
}

chmod +x run.sh.

Step 5: cron entry

crontab -e

Add:

# the nightly inventory audit, 23:00 AEST nightly (13:00 UTC during AEDT, 13:00 UTC during AEST too if server is in UTC)
0 13 * * * /opt/agents/skincare-inventory/run.sh

The server is in UTC. 23:00 Melbourne time is 13:00 UTC during AEDT and 13:00 UTC during AEST (Melbourne uses AEDT October-April, AEST otherwise). For client deployments we accept the one-hour drift twice a year; if you need precision, use a wrapper that calculates the local-time offset.

Step 6: smoke test

./run.sh

You should see a Slack message in #overnight-inventory within 60-90 seconds. If you don’t, check last-run.log, it’ll show what Claude actually did.

Step 7: budget guardrails

In Anthropic Console:

  • Set a hard spending cap of $30 USD/month on the API key this agent uses.
  • Email alert at 50% and 80%.
  • Use a dedicated API key for this agent so spend is attributable.

What it costs to run

Each nightly run does about 15-30 tool calls, ~40k input tokens, ~5k output. With caching, that’s roughly $0.08 AUD per run. 30 runs/month = $2.40 AUD. Real bills: we average $4-6 AUD/month including a few re-runs and occasional poking.

Common failures + fixes

  • Shopify rate limit. Reduce concurrent product reads in your prompt. Tell Claude to fetch in batches of 50.
  • Slack webhook silently rejected. Check the webhook URL is valid; Slack rotates these without warning if compromised.
  • Claude hits the turn cap. Increase --max-turns cautiously. Or tighten the prompt so the work fits.
  • Output drifts in format. Reinforce the format requirement in CLAUDE.md and add an example.

Where to take this next

Once the inventory agent is reliable, the natural follow-ons are:

  • A morning agent that summarises overnight orders + flags any suspicious ones
  • A weekly agent that runs a cohort revenue analysis and writes the result to a Notion page
  • A monthly agent that drafts the marketing report from Meta Ads + Shopify data

Same template each time: CLAUDE.md → MCP → settings → wrapper → cron. The first one is the hardest; subsequent agents take 30-45 minutes.

If you want us to build the first one for you and then teach you the pattern, that’s literally the Quick Start package.

Common questions

Can Claude Code run unattended on a server?
Yes. Headless mode (`claude --print 'do X'`) runs once and exits with the result. Pair with cron, GitHub Actions or a systemd timer. We run several agents on a Hetzner VPS.
How do I stop it from running up a huge bill?
Three layers. (1) Anthropic Console budget alert on the API key. (2) --max-turns flag on the agent invocation. (3) Per-task token cap via ANTHROPIC_MAX_TOKENS env var. All three.
Does the agent need to be on my laptop or can it live on a server?
Both work. We run the inventory-audit agent on a Hetzner VPS so it runs even when our laptops are off. Setup is the same, install Node, install Claude Code, set the API key, write the cron entry.

Want this built for your business?

Book a free 30-minute AI audit. We'll map your business and show you exactly which systems we'd build first. No pitch deck, no scoping fee.

Book my free AI audit