cd /news/ai-agents/three-things-already-in-your-claude-… · home topics ai-agents article
[ARTICLE · art-82615] src=gist.github.com ↗ pub= topic=ai-agents verified=true sentiment=· neutral

Three things already in your Claude Code that most people haven't touched: routines, background agents, stacked skills.

An engineer detailed how to set up routines, background agents, and stacked skills in Claude Code, sharing a repo-health check routine that runs scheduled cloud agents to verify README instructions. The routine uses a self-contained prompt, cron expressions in UTC, and a one-off run_once_at option for testing, with notifications and transcripts available via the routine page.

read10 min views1 publishedJul 31, 2026

A routine is a scheduled cloud agent. It is not a local cron job. Each run spawns an isolated session in Anthropic's cloud with its own git checkout. It cannot see your laptop, your local files, or your local env vars. Everything it needs has to come from the repo it clones and from the prompt.

Here is the repo-health check I set up, step by step.

Mine: go through every project in ai-weekend-builds

and confirm the install and run steps in each README actually work.

The prompt is the part that matters most. The cloud agent starts with zero context, so it has to be self-contained. Mine says, in order: map the repo, read each README, extract the exact documented commands, actually run them, record the real error output. Then a list of things to flag — missing README, commands pointing at files that don't exist, missing .env.example

when the code reads env vars, lockfile out of sync, version requirements that conflict with what the code needs.

Two lines that do a lot of work:

Do NOT fix anything. Do NOT commit, push, or open a pull request. This run is read-and-report only.
Be specific and paste real command output rather than summarizing it.

Without the first, the agent will helpfully start editing your repo. Without the second, you get "a few projects had issues" instead of a stack trace.

Cron is five fields, always in UTC, minimum interval one hour. */30 * * * *

gets rejected.

0 9 * * 1-5     weekdays at 9am UTC
0 12 * * *      daily at 12:00 UTC
30 14 * * 1     Mondays at 2:30pm UTC
0 8 1 * *       first of the month, 8am UTC

I'm in Europe/Belgrade, which is UTC+2 in summer. So 7am for me is 0 5 * * *

. Do the conversion, don't eyeball it.

For a one-off you use run_once_at

instead of cron_expression

, an RFC3339 UTC timestamp that must be in the future:

"run_once_at": "2026-07-31T15:54:30Z"

The one-hour minimum does not apply to run_once_at

. That's the escape hatch when you want to watch it fire in ten minutes instead of waiting until tomorrow. I used exactly that to test this routine before switching it to a daily schedule.

{
  "name": "Repo health — ai-weekend-builds",
  "run_once_at": "2026-07-31T15:54:30Z",
  "enabled": true,
  "notifications": { "channel": { "email": false, "push": true, "slack": false } },
  "job_config": {
    "ccr": {
      "environment_id": "env_...",
      "session_context": {
        "model": "claude-sonnet-5",
        "sources": [
          { "git_repository": { "url": "https://github.com/kju4q/ai-weekend-builds" } }
        ],
        "allowed_tools": ["Bash", "Read", "Write", "Edit", "Glob", "Grep"]
      },
      "events": [
        { "data": {
            "uuid": "<fresh lowercase v4 uuid>",
            "session_id": "",
            "type": "user",
            "parent_tool_use_id": null,
            "message": { "role": "user", "content": "YOUR PROMPT HERE" }
        } }
      ]
    }
  }
}

Notes from actually doing this:

sources

is what gets cloned. No repo listed, no repo in the sandbox.allowed_tools

needsBash

if the agent is going to run install commands. Mine has it. It does not needWebFetch

/WebSearch

, so I left those out.- The uuid

is a fresh v4 you generate yourself, per routine. - The environment id comes from your available environments. Most people have one, called Default.

Two places.

Push notification, from notifications.channel.push: true

. That's the one I use. Email and Slack are the other two channels and they're independent booleans, so you can have all three or none. If you set none, the run still happens and you just have to go look.

The routine page, at https://claude.ai/code/routines/{ROUTINE_ID}

. The create call returns the id. Every run's full transcript lands there, so you can read what the agent actually ran, not just its summary.

  • Connectors get attached even when you don't ask. My repo-health routine came back with Gmail, Google Calendar, and Claude Code Remote attached, because they're connected at the account level. Worth knowing if you care what a scheduled agent can reach.
  • You can't delete a routine from the CLI. Only from https://claude.ai/code/routines

. Youcandisable it with"enabled": false

. - A one-shot auto-disables after it fires and shows ended_reason: "run_once_fired"

. To reuse it, update it with a newrun_once_at

or swap in acron_expression

. - The agent runs in the cloud. If your project needs a database, an API key, or a local service, it will fail there and pass on your machine. Write the prompt so a failure to install is a finding, not a crash.

start with the thing you do manually every morning.

The flow: you hand a task to a background agent, keep working, and get a notification when it's done. You are not sitting and watching it.

Hand off the task. You describe the work and it runs in its own context, separate from yours. You keep going in the main session.

Isolate it if it writes files. A background agent can run in its own git worktree, meaning a fresh checkout on disk. This matters the moment you have more than one agent editing files, or you want your working tree untouched while it works. It costs a little setup time and disk per agent, so use it when there's actual write contention, not by default.

Say what "done" means, explicitly. This is the part people skip. Committing, pushing, and opening a draft PR are not automatic. They happen because the prompt told the agent to do them, in those words. Something like:

When the work is complete: commit with a descriptive message,
push the branch, and open a DRAFT pull request against main
with a summary of what changed and what you did not cover.

Draft, specifically. A draft PR is a review surface, not a merge request. It means you can hand off work freely without anything landing while you're not looking.

The notification. Background work reports back into the session that started it when it finishes. You get told; you don't poll. Polling on a timer for work that already notifies you is wasted effort.

Check these in order, cheapest first:

The prompt. Does it actually say to open a PR? An agent that was asked to "fix the failing test" fixes the failing test. Most of the time this is the whole answer.Push permission in the environment where the agent ran. A cloud agent's sandbox has its own git credentials. If it can't push the branch, it can't open the PR, and the failure shows up as a push error partway down the transcript rather than at the end.Explicit forbidding. If your prompt or a project instruction says not to commit or push without asking — mine says exactly that for the repo-health routine, on purpose — the agent will obey it and stop. Read your own instructions before blaming the tool.

Read the run transcript on the routine page. The reason is almost always sitting in it.

Skills are packaged instructions for a specific kind of task: a review checklist, a deploy sequence, a house style. You invoke one with /name

.

Stacking means running several in one line so they compose into a single pass instead of separate ones.

Three skills, one argument line, one pass:

/q-research /q-building /q-thinking apply research-workflow and blind-spot-finder
to this task: research what shipped in claude code this month and identify the most
underused feature, then draft a short post about it. Then critique against
~/.claude/TASTE.md and fix violations before showing me.

All three skills load into the same turn. The argument text goes to each one. They do not run as three separate passes handing files to each other; they arrive as three sets of instructions over a single piece of work, and you name which technique you want from each. That last part matters. q-thinking

alone ships six techniques. Without naming blind-spot-finder

, you are letting the model pick.

What came back was one pass with four labelled stages: the research structure, the findings, the gaps, then the taste critique. Research fed the draft. The draft went through the taste file. No copy-paste between steps.

I added skills to .claude/skills/

and they did not exist. Not an error message, just nothing when I typed /

.

The skill list is read when the session starts. Adding a directory to a running session does nothing. Restart, then the skill is there.

This is the entire bug most of the time. Before debugging your frontmatter, quit and reopen.

Every SKILL.md

needs a YAML block at the very top, before anything else:

---
name: q-thinking
description: Use this skill when the user needs to understand a problem before
  solving it. Activate for complex situations where the answer is not clear, where
  assumptions need surfacing, or where the user feels stuck or overwhelmed.
---

Two keys. name

is what you type after the slash and it has to match the directory name. description

is not documentation. It is the matching text: the model reads it to decide whether this skill applies to what you just asked. Write it as trigger conditions, not as a summary of the contents. Mine all start with "Use this skill when" and then list the situations. That phrasing is doing work.

Missing block, or a block that is not the first thing in the file, and the skill is invisible. Same symptom as the restart problem, different cause, which is why you check the restart first.

Layout that works:

.claude/skills/
  q-thinking/
    SKILL.md          <- frontmatter here
    techniques/
      blind-spot-finder.md
      complexity-mapper.md

SKILL.md

is the index. Keep the long technique text in separate files and let the skill point at them. It loads what it needs instead of everything.

The last skill in the stack is not a skill. It is a file.

~/.claude/TASTE.md

holds my content rules: banned words, banned punctuation, anti-preferences, and four things every piece has to do. It ends with one instruction:

Before presenting any output, review it against every rule in this file.
If it violates a rule, fix it before showing me. If unsure whether something
violates a rule, flag it and ask.

Putting it last in the stack means it runs on the finished draft rather than on my prompt. The research and the writing happen without it in the way, then everything passes through it before I see it.

The clause that earns its place is the second one. On this run, one of my rules is "test it before teaching it." The draft post was about a feature it had confirmed existed but had never actually run. Instead of quietly shipping it or silently dropping the claim, it flagged the gap and asked whether to run a real test first. A gate that only deletes violations would have deleted the interesting sentence. A gate that can ask hands the decision back to me.

Worth knowing: my own rules ban em dashes, and the sections above this one are full of them. The gate applies to what it writes, not to what I already wrote.

When the output of each stage is the input to the next and you want them to share context, research feeding a draft, the draft passing through a taste file, stack them. When the steps are independent and you would want to inspect or correct the result between them, run them separately.

That's the whole rule. Stack when the handoff is the point. Don't stack when you want a checkpoint in the middle.

Built by @kju4q, more at github.com/kju4q

── more in #ai-agents 4 stories · sorted by recency
── more on @claude code 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/three-things-already…] indexed:0 read:10min 2026-07-31 ·