finops-toolkit
AGENTS.md623 starsChanged 2 months agoMITView on GitHub
The FinOps Toolkit is an open-source collection of tools for adopting and implementing FinOps capabilities in the Microsoft Cloud. It contains templates, PowerShell modules, workbooks, optimization engines, and supporting documentation organized in a modular architecture. The FinOps hubs solution is actively migrating to a namespace-based modular structure: Templates use a multi-target build system that generates: Key patterns:
- Deletes or force-pushes
- Commits and pushes
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,542 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repository5 other files it gives its agents.
- src/templates/finops-hub-copilot/copilot-instructions.mdCopilot instructions
- microsoft-writing-style-guideSkill
- support-reportSkill
- support-sweepSkill
- finops-toolkitSkill
The file
We split this AGENTS.md into the rules it gives an agent
8 rules. About 0 are common, 3 are distinctive, and 5 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
5
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 124
Use newApp() and newHub() functions from fx/hub-types.bicep for consistent resource naming
- Very specific: line 125
Follow the conditional deployment pattern: resource foo 'type' = if (condition) { ...
- Distinctive: line 131
All public functions must have comment-based help
- Very specific: line 132
Use approved verbs from Get-Verb
- Distinctive: line 140
Unit tests: test isolated function behavior with mocks
- Very specific: line 202
AI agents must ask for explicit approval: before executing any git write operation (commit, push, merge, rebase).
- Very specific: line 213
Always follow the content and coding standards defined in docs-wiki/Coding-guidelines.md
- Distinctive: line 220
Commit messages: Use conventional commit format
≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Agent Instructions
This file provides guidance to AI Agents when working with code in this repository.
Repository Overview
The FinOps Toolkit is an open-source collection of tools for adopting and implementing FinOps capabilities in the Microsoft Cloud. It contains templates, PowerShell modules, workbooks, optimization engines, and supporting documentation organized in a modular architecture.
Common Commands
Building and Development
# Build entire toolkit
npm run build
# or
pwsh -Command ./src/scripts/Build-Toolkit
# Build FinOps hubs
pwsh -Command ./src/scripts/Build-Toolkit finops-hub
# Build specific components
npm run build-ps # PowerShell module only
pwsh -Command ./src/scripts/Build-Bicep # Bicep templates
pwsh -Command ./src/scripts/Build-Workbook # Azure Monitor workbooks
pwsh -Command ./src/scripts/Build-OpenData # Open data files
# Deploy for testing
npm run deploy-test
# or
pwsh -Command ./src/scripts/Deploy-Toolkit -Build -Test
# Package for release
npm run package
# or
pwsh -Command ./src/scripts/Package-Toolkit -BuildTesting
# Run PowerShell unit tests
npm run pester
# or
pwsh -Command Invoke-Pester -Output Detailed -Path ./src/powershell/Tests/Unit/*
# Run integration tests
pwsh -Command ./src/scripts/Test-PowerShell -Integration
# Run specific test categories
pwsh -Command ./src/scripts/Test-PowerShell -Hubs -Exports
# Lint PowerShell code
pwsh -Command ./src/scripts/Test-PowerShell -LintBicep Development
# Validate Bicep templates
bicep build path/to/template.bicep --stdout
# Test template deployment
az deployment group what-if --resource-group myRG --template-file template.bicepArchitecture and Code Organization
High-Level Structure
/src/templates/- ARM/Bicep infrastructure templates with modular namespace organization/src/powershell/- PowerShell module with public/private functions and comprehensive tests/src/optimization-engine/- Azure Optimization Engine for cost recommendations/src/workbooks/- Azure Monitor workbooks for governance and optimization/src/open-data/- Reference data (pricing, regions, services) with utilities/src/scripts/- Build automation and development tools/docs/- Jekyll documentation website/docs-mslearn/- Microsoft Learn documentation website/docs-wiki/- GitHub wiki documentation
Current Architectural Reorganization
The FinOps hubs solution is actively migrating to a namespace-based modular structure:
Microsoft.FinOpsHubs/- Core FinOps Hub infrastructure modulesMicrosoft.CostManagement/- Cost management exports and schemasfx/- Shared foundation components (hub-types, scripts, utilities)
Template Architecture
Templates use a multi-target build system that generates:
- Azure Quickstart Templates (ARM JSON)
- Bicep Registry modules
- Standalone deployments
- Azure portal UI definitions
Key patterns:
.build.configfiles control build behavior per templatesettings.jsoncontains component-specific configurationftkver.txtfiles maintain version synchronization- Conditional resource deployment based on parameters
PowerShell Module Structure
Public/- User-facing cmdlets (Get-, Set-, New-*, etc.)Private/- Internal utilities and helpersTests/Unit/- Pester unit tests with mockingTests/Integration/- End-to-end Azure integration tests- Module manifest defines exports and dependencies
Data Flow and Integration
- Open data provides reference information consumed by templates and PowerShell
- Build scripts orchestrate compilation across all components
- Version management is centralized through
Update-Version.ps1 - Templates reference shared schemas and types from
fx/namespace
Key Development Patterns
Template Development
- Use
newApp()andnewHub()functions fromfx/hub-types.bicepfor consistent resource naming - Follow the conditional deployment pattern:
resource foo 'type' = if (condition) { ... } - Implement proper parameter validation with
@allowed,@minValue,@maxValue - Include telemetry tracking via
defaultTelemetryparameter
PowerShell Development
- All public functions must have comment-based help
- Use approved verbs from
Get-Verb - Implement comprehensive parameter validation
- Support
-WhatIfand-Confirmfor destructive operations - Include Pester tests for all functions
Testing Strategy
- Lint tests validate syntax and coding standards
- Unit tests test isolated function behavior with mocks
- Integration tests perform end-to-end validation against Azure
- Template validation uses
bicep buildand ARM what-if deployments
Build System Integration
The PowerShell-based build system:
- Compiles templates to multiple target formats
- Validates all code before packaging
- Maintains version consistency across components
- Generates release artifacts automatically
Version Management
- Central version in
package.json(currently 12.0.0) - Synchronized across all components via build scripts
- Individual
ftkver.txtfiles distributed to modules - Git tags correspond to release versions
Repository Conventions
Branch Strategy
dev- Main integration branch- Feature branches merge into
dev - Releases are tagged from
dev - Branch names must be prefixed with the GitHub username (e.g.,
{username}/my-feature)
Git Operations Policy
This repository supports production infrastructure managing significant revenue. All git operations on shared branches (main, dev, features/*) must be non-destructive and preserve full commit history. On personal branches ({username}/*), the only history-rewriting operations permitted are rebase and force-push with lease (see below), to keep PR history clean against origin/dev.
Changes reach dev only through squash-merge PRs; merges to main are blocked. A personal branch counts as shared while another branch or PR is based on it. Always fetch before rewriting a personal branch, because the update-mslearn-dates.yml workflow and maintainers can push to it.
Permitted operations:
git add,git commit,git push(standard push; force-push only as described under prohibited operations)git merge(shared branches only)git checkout,git switch,git branch(branch creation and switching)git worktree add,git worktree remove,git worktree prune(worktree lifecycle)git fetch,git pull(with merge on shared branches;git pull --rebaseon personal branches)git stash,git stash pop(temporary local state management)git status,git log,git diff,git show(read-only inspection)
Prohibited operations:
git rebaseon a shared branchgit push --force— never permitted. On a personal branch, push withgit push --force-with-lease --force-if-includesonly, after integrating remote commits. Never permitted on a shared branch.git reset --hardto a state behind the remote (discarding pushed commits)git filter-branch,git reflog-based history manipulation- Any other history rewrite of pushed commits (for example, squashing with
git reset --soft)
Conflict resolution: On a personal branch, sync with dev using only git rebase origin/dev then force-push with lease; never merge dev into it, or the PR shows merged files as changed. On a shared branch, use only git merge origin/dev.
Common conflict patterns in this repository:
ms.datefields indocs-mslearn/files — Microsoft Learn docs usems.datein YAML front matter. A CI workflow (.github/workflows/update-mslearn-dates.yml) automatically updatesms.dateto today's date fordocs-mslearn/**/*.mdfiles that have body content changes (changes outside YAML frontmatter). Metadata-only changes (e.g., updating onlyms.authoror other frontmatter fields) do not triggerms.dateupdates. On protected branches where the bot cannot push, you must updatems.dateto today's date (MM/DD/YYYYformat) manually when you modify the body content of anydocs-mslearn/markdown file. When resolving merge conflicts onms.date, always set the date to today — not either side's value..gitignoreadditions — Both sides may add new ignore entries to the end of the file. Keep entries from both sides; they are additive and independent.src/scripts/Update-Version.ps1— This script has multiple independent version-update blocks (PowerShell, Bicep, plugin.json, survey IDs, etc.). When both sides add new blocks, keep both — they operate on different file sets and do not conflict logically.docs-mslearn/toolkit/changelog.md— Both sides may add entries under the same version heading. Keep entries from both sides in logical order (plugin entries, then component entries).
AI agents must ask for explicit approval before executing any git write operation (commit, push, merge, rebase). Read-only git commands (status, log, diff, branch --list, worktree list) do not require approval.
File Organization
- Templates follow namespace/module/component structure
- PowerShell follows standard module layout
- Documentation uses Jekyll conventions
- Build artifacts are generated, not checked in
Coding Standards
- Always follow the content and coding standards defined in
docs-wiki/Coding-guidelines.md - Content (text strings): Always use the Microsoft style guide skill
.claude/skills/microsoft-writing-style-guide/SKILL.mdand always use sentence casing except for proper nouns - Bicep: Follow Azure Bicep style guide
- PowerShell: Use PowerShell best practices and approved verbs
- KQL: Never use
tolower()/toupper()in comparison position — KQL string operators are already case-insensitive (_csvariants are the case-sensitive ones). Usehasfor whole terms and path phrases,=~/!~for equality,in~/has_anyfor sets. Reservecontainsfor genuine substring matching (needle fused inside a larger token) and justify it in the allowlist insrc/powershell/Tests/Unit/HubsKqlOperators.Tests.ps1, which enforces both rules on every PR. See the KQL section ofdocs-wiki/Coding-guidelines.md - KQL joins: Never write a bare
| join— always statekind=explicitly (theinneruniquedefault deduplicates the left side and silently drops rows; enforced bysrc/powershell/Tests/Lint/KqlJoinKinds.Tests.ps1, added in PR #2225). Preferlookupoverjoinfor enriching a fact table from a small dimension (ADX/Log Analytics only — not available in Azure Resource Graph), dedupe the dimension side withsummarize take_any(...) by <key>(notdistinct), and usekind=leftantifor exclusions instead ofkind=leftouter+where isempty(...)— except in ARG, which rejectslookupand all semi/anti flavors (verified live), so exclusions there use theleftouter+isempty()emulation with a key-unique right side. See the "Joins and lookups" section ofdocs-wiki/Coding-guidelines.md - Documentation: Use markdown with consistent formatting
- Commit messages: Use conventional commit format
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

