Thu Nov 19 · time TBA
Agentic DevOps: How I Use Claude Code and Azure DevOps to Ship Code While I Sleep
Every night a scheduled Azure Pipeline picks up one work item tagged claude-ready, has Claude Code build it, runs the build and tests, and opens a pull request. In the morning you review it like a teammate's PR. Here's how to set it up: six steps, one afternoon.
What you need
- An Azure DevOps project with a repo and Azure Pipelines
- An Anthropic API key (platform.claude.com)
- Azure Key Vault (optional; a secret pipeline variable works too)
- Claude Code installed on your machine
Step 1: CLAUDE.md, set it up once
You won't read this file day to day. Claude does, on every run, at your desk or at 2 AM. Set it up right once, then let Claude keep it current.
- 1.Run
/initin Claude Code. It writes the first version from your code. - 2.Tell Claude what to add: build and test commands, your coding patterns, which packages to use.
- 3.Add a never list: config files like
appsettings.json, connection strings,git add -A.
Every few weeks, ask Claude
Check CLAUDE.md against the current code. List what's out of date or missing, then fix it.Step 2: The work item is the spec
Write what's broken and what should happen. Describe the behavior, not the implementation. Claude knows your code base. Keep it short: the description gets cut off at 1,000 characters. Big job? Split it into several items.
What most backlogs look like
- Title:
- Fix the export button
- Description:
- It doesn't work sometimes. Make it work.
- Tags:
- (none)
Claude-ready
- Title:
- CSV export returns a 500 when a report has more than 10,000 rows
- Description:
- Large reports should export and download like small ones.
- Tags:
- claude-ready
The tag is the on switch. Nothing gets picked up unless you tag it claude-ready.
Save this query (Boards → Queries → New query → Editor)
SELECT [System.Id], [System.Title], [System.State]
FROM WorkItems
WHERE [System.Tags] CONTAINS 'claude-ready'
AND [System.AreaPath] UNDER '<Your Project>'
AND [System.State] <> 'Removed'
AND [System.State] <> 'Closed'
ORDER BY [Microsoft.VSTS.Common.Priority] ASCWhy one item a night
Step 3: A PAT (Personal Access Token)
A PAT is a password for a script. It lets the pipeline act as you in Azure DevOps.
- Where: Azure DevOps → User settings (top right) → Personal access tokens → New Token
- Scopes: Code (Read & write) and Work Items (Read & write)
- It expires. Put the expiry date on your calendar. Mine expired once and the nightly runs failed quietly.
Step 4: Key Vault, where the keys live
Never put keys in the repo or the YAML.
- 1.In Azure Key Vault, add two secrets:
AnthropicApiKeyandAzureDevOpsPat. - 2.In Azure DevOps → Project settings → Service connections, create (or reuse) an Azure Resource Manager connection.
- 3.Give that connection's identity permission to read secrets on the vault: Get + List (access policy) or the "Key Vault Secrets User" role (RBAC).
- 4.Add this as the first step of the nightly stage:yaml
- task: AzureKeyVault@2 inputs: azureSubscription: '<your service connection>' KeyVaultName: '<your key vault>' SecretsFilter: 'AnthropicApiKey,AzureDevOpsPat'
No Key Vault?
Cost
claude setup-token can bill your Pro/Max plan instead.) Set a spend limit and low-balance alerts at platform.claude.com. One complicated item can eat a lot of credits overnight.Step 5: Have Claude Code write the nightly stage
Don't write the YAML yourself. Paste this into Claude Code in your repo:
Add a stage to azure-pipelines.yml that runs Claude Code on our Azure DevOps work items overnight.
- Runs on a schedule at 2 AM Eastern, Monday-Friday, and when I click Run. Never on a code push.
- Pulls AnthropicApiKey and AzureDevOpsPat from our Key Vault through the existing service connection.
- Installs Claude Code, sets a git identity of "Claude (Automated)", and uses the PAT to push branches.
- Takes ONE work item tagged claude-ready, implements it, runs dotnet build and dotnet test, and
opens a PR. If anything fails: no PR, tag it claude-blocked.
- Hard time limit of 90 minutes.
Before you build anything, ask me five questions about what I'm about to build.What you should get looks roughly like this:
schedules:
- cron: '0 7 * * 1-5' # cron is UTC: 07:00 UTC = 2 AM Eastern (standard time)
displayName: 'Nightly Claude Development'
branches: { include: [ main ] }
always: true
- stage: ClaudeDevelopment
dependsOn: []
condition: or(eq(variables['Build.Reason'], 'Schedule'),
eq(variables['Build.Reason'], 'Manual'))
jobs:
- job: ClaudeImplementation
timeoutInMinutes: 120The condition is what keeps Claude out of your normal CI. A regular push builds and deploys. It never wakes Claude up.
Step 6: The command and the standing prompt
You don't run this yourself. Claude Code wrote it into the nightly stage in Step 5. This is what's inside the step named "Claude autonomous development": one claude -p command, and the prompt it runs is the text inside the quotes.
The one command
claude -p '
You are working autonomously on <Project>.
Build: dotnet build <Solution>.sln -c Release
Test: dotnet test <TestProject>
1. Query Azure DevOps for work items tagged claude-ready (Azure DevOps MCP server).
2. For the top item: read it, implement it, build and test. If both pass, branch
claude/workitem-{id}, commit, push, and open a PR. Swap claude-ready for
claude-implemented and comment on the item with a summary.
3. If it fails: comment why and tag claude-blocked. No PR.
4. Maximum work items to process: 1 per run.
Do not ask questions. Follow the patterns in CLAUDE.md.
Do NOT modify appsettings.json or connection strings. Never git add -A.
' \
--dangerously-skip-permissions \
--no-session-persistence \
--verbose \
--max-turns 200- -p
- Run once and exit. No chat window. Prompt in, work done, quit.
- --dangerously-skip-permissions
- Don't stop to ask “can I run this?” Nobody's awake to click Yes.
- --max-turns 200
- A ceiling on how many steps it takes before it has to stop.
- --no-session-persistence
- Don't save the conversation. Every night starts clean.
Everything in this step, including the prompt, is in the YAML that Step 5 generated. To change the rules, change the YAML.
Which model?
--model sonnet (or --model opus) to the claude -p line. Use an alias, not a dated model name: dated names get retired and the nightly stops with a 404.Why skipping permissions is OK here
--allowedTools with an explicit list instead.The safety net
Claude may only open a PR if dotnet build and dotnet test both pass. For UI checks, add Playwright for .NET (the Microsoft.Playwright NuGet package). The tests are written in C#, run inside dotnet test, and the same gate covers them.
Run it
- 1.Pipelines → your pipeline → Run pipeline → main → Run
- 2.Open the run → the Claude stage → the job → the Claude step, and watch the log
- 3.Tonight the schedule does it for you
The morning review checklist
- Open the PR: linked work item, Claude's summary comment, files changed. Is it the right size for the ask?
- Pull the branch and run it locally
- Test it: click through the feature like a user would
- Read the diff. Would you have written it this way? Watch config and secrets. Push back if it over-engineered.
- Merge, or improve the work item and re-tag it
The guardrails
- Opt-in tag: only items tagged
claude-ready - One item a night
- Hard limits: 90-minute timeout, 200 turns
- You merge. It can open a PR; only you merge, and merging is what deploys. (Teams: require a reviewer on main with a branch policy.)
What went wrong (so it doesn't happen to you)
- A model got retired. The model my pipeline named started returning 404s. Watch the retirement notices. The fix: pin an alias like
--model sonnetinstead of a dated model name (see "Which model?" in Step 6). - The PAT expired. Calendar reminder, and rotate it before it expires.
- The overnight bill. One complicated item burned through my credits. Set spend alerts and keep items small.
- Overlapping work. Several items at once means branches that conflict. One a night.
Docs worth bookmarking
- Claude Code: headless mode and authentication (code.claude.com)
- Azure Pipelines: scheduled triggers (learn.microsoft.com)
- Azure Key Vault task in Azure Pipelines (learn.microsoft.com)
- Azure DevOps: personal access tokens (learn.microsoft.com)
- Playwright for .NET (playwright.dev/dotnet)
Slides
Slides (PDF) will be posted here after the session.
How to reach me
Working on something like this? Let's talk.
Start a conversation