{"_id":"@costguard/costguard-mcp","name":"@costguard/costguard-mcp","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@costguard/costguard-mcp","version":"0.1.0","description":"Audit your repos and cloud providers for CI and infrastructure cost leaks. Ships a CLI and an MCP server for AI coding agents (Claude Code, Codex, any MCP host).","type":"module","private":false,"license":"MIT","author":{"name":"Mark Laursen"},"homepage":"https://github.com/mbanderas/costguard#readme","repository":{"type":"git","url":"git+https://github.com/mbanderas/costguard.git"},"bugs":{"url":"https://github.com/mbanderas/costguard/issues"},"keywords":["cost","cost-optimization","finops","ci","github-actions","cloud-cost","mcp","mcp-server","model-context-protocol","claude-code","audit"],"engines":{"node":">=20"},"publishConfig":{"access":"public"},"bin":{"costguard":"dist/cli/index.js","costguard-mcp":"dist/mcp/server.js"},"scripts":{"build":"node scripts/bundle.mjs && node scripts/bundle-mcp.mjs","build:mcp":"node scripts/bundle-mcp.mjs","check:dist":"node scripts/check-dist.cjs","verify":"pnpm typecheck && pnpm lint && pnpm test && pnpm check:dist","ci:docker":"gh act workflow_dispatch -j checks","typecheck":"tsc -p tsconfig.json --noEmit","test":"vitest run","test:watch":"vitest","lint":"eslint . --quiet","dev":"tsx src/cli/index.ts"},"dependencies":{"@modelcontextprotocol/sdk":"^1.29.0","commander":"^12","cron-parser":"^4","diff":"^9.0.0","js-yaml":"^4","yaml":"^2.9.0","zod":"^3"},"devDependencies":{"@eslint/js":"^9","@types/js-yaml":"^4","@types/node":"^22","esbuild":"0.28.1","eslint":"^9","tsx":"^4","typescript":"^5","typescript-eslint":"^8","vitest":"^2"},"_id":"@costguard/costguard-mcp@0.1.0","gitHead":"25785aacb7051258676f849cd4a6272000a741e0","_nodeVersion":"20.20.2","_npmVersion":"10.8.2","dist":{"integrity":"sha512-zJ5O53DXOeIeG2MC1a2mSHqwVIvO8BmvaIT3KbUPXdr49YZ7uM7HXlN6YkSbCGzHRISsHViBlopKY+dL/6SwtA==","shasum":"5a71a831a57119b35724d711615e98f0f74da567","tarball":"https://registry.npmjs.org/@costguard/costguard-mcp/-/costguard-mcp-0.1.0.tgz","fileCount":31,"unpackedSize":2834721,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@costguard%2fcostguard-mcp@0.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIF+w9Adh8Zh8kv8fzVBkV68Zgs/2dK1mVpvmMmlOR1kSAiBGfIkG/R6O0t/ROnumBKtCbVTCEiG/0LhJ0TLa8sLoyg=="}]},"_npmUser":{"name":"marklaursen","email":"markbanderas@gmail.com"},"directories":{},"maintainers":[{"name":"marklaursen","email":"markbanderas@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/costguard-mcp_0.1.0_1781736774690_0.32800396793682185"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-17T22:52:54.519Z","0.1.0":"2026-06-17T22:52:54.869Z","modified":"2026-06-17T22:52:55.266Z"},"maintainers":[{"name":"marklaursen","email":"markbanderas@gmail.com"}],"description":"Audit your repos and cloud providers for CI and infrastructure cost leaks. Ships a CLI and an MCP server for AI coding agents (Claude Code, Codex, any MCP host).","homepage":"https://github.com/mbanderas/costguard#readme","keywords":["cost","cost-optimization","finops","ci","github-actions","cloud-cost","mcp","mcp-server","model-context-protocol","claude-code","audit"],"repository":{"type":"git","url":"git+https://github.com/mbanderas/costguard.git"},"author":{"name":"Mark Laursen"},"bugs":{"url":"https://github.com/mbanderas/costguard/issues"},"license":"MIT","readme":"# CostGuard\n\n<p align=\"center\">\n  <img src=\"assets/costguard-banner.png\" alt=\"CostGuard — a robot sea captain steering a boat named costguard through waters of dollars, CPUs, clocks, and clouds\" width=\"720\">\n</p>\n\n<p align=\"center\">\n  <a href=\"https://www.npmjs.com/package/@costguard/costguard-mcp\"><img src=\"https://img.shields.io/npm/v/@costguard/costguard-mcp?label=npm&color=2E9E6B\" alt=\"npm version\"></a>\n  <a href=\"https://github.com/mbanderas/costguard/actions/workflows/ci.yml\"><img src=\"https://img.shields.io/github/actions/workflow/status/mbanderas/costguard/ci.yml?branch=master&label=CI\" alt=\"CI status\"></a>\n  <a href=\"LICENSE\"><img src=\"https://img.shields.io/github/license/mbanderas/costguard?color=2E9E6B\" alt=\"MIT license\"></a>\n  <a href=\"https://nodejs.org\"><img src=\"https://img.shields.io/node/v/@costguard/costguard-mcp\" alt=\"node version\"></a>\n</p>\n\nCostGuard audits your repos and cloud providers for CI and infrastructure cost\nleaks. It is built for developers who run several projects across GitHub Actions,\nVercel, Supabase, Railway, Netlify, Neon, Cloudflare, and more, and want a single\ncommand that surfaces what is being wasted and exactly how to fix it. On repositories that have never been\noptimized, the static audit alone typically reduces CI spend by 60–80%.\n\n<p align=\"center\">\n  <img src=\"assets/chart-ci-savings.svg\" alt=\"Observed CI cost reduction: 60-80% typical on repositories never optimized, up to 80% best observed\" width=\"720\">\n</p>\n\n---\n\n## Install\n\nCostGuard installs three ways. The plugin paths are zero-build and zero-`npm`\n(they ship a prebuilt, self-contained bundle); the npm package gives you the CLI\nand the MCP server anywhere.\n\n### Claude Code\n\n```sh\n/plugin marketplace add mbanderas/costguard\n/plugin install costguard@costguard\n```\n\nAdds `/costguard-audit`, `/costguard-fix`, `/costguard-live`, and the full\n`costguard` skill (scan, providers, registry, report, digest). No build step, no\n`npm install`.\n\n### Codex\n\n```sh\ncodex plugin marketplace add mbanderas/costguard\ncodex plugin add costguard@costguard\n```\n\nAdds the bundled `costguard` skill to Codex CLI and Desktop.\n\n### npm / any MCP host\n\nRun the MCP server directly — no install:\n\n```sh\nnpx -y @costguard/costguard-mcp\n```\n\nInstall the MCP server and the `costguard` CLI globally (both bins):\n\n```sh\nnpm i -g @costguard/costguard-mcp\n```\n\nRun the CLI ad-hoc without installing:\n\n```sh\nnpx -y -p @costguard/costguard-mcp costguard\n```\n\n`npx -y @costguard/costguard-mcp` launches the MCP server directly because the\npackage name matches its bin entry point — drop it straight into any MCP host's\nserver config.\n\n> **Other CLIs / Desktop apps** — one command drops a thin `/costguard` adapter\n> into Cursor, Gemini CLI, Cline, Windsurf, or a Codex project:\n>\n> ```sh\n> npx -y -p @costguard/costguard-mcp costguard install --target <host|auto>\n> ```\n>\n> `--target auto` detects the host; the adapter is no-clobber and idempotent. Run\n> `costguard install --help` for the full target list.\n\n---\n\n## What it finds\n\n**Static half (zero credentials).** Reads `.github/workflows/*.yml` and\napplication code to detect redundant CI triggers (`push` + `pull_request` on the\nsame branch), missing `timeout-minutes`, missing concurrency cancellation,\n`paths-ignore` gaps that run CI on doc-only commits, and over-scheduled crons. No\nAPI call, no token needed — always safe to run.\n\n**Billing half (read-only, opt-in).** When a provider token is present,\nreconciles live billed resources against a declared allowlist and flags\n**orphaned** resources (billed but not listed) and **over-provisioned** resources\n(larger or more capable than declared), each with a best-effort estimated monthly\ncost. Covers thirteen providers: **GitHub**, **Vercel**, **Supabase**,\n**Railway**, **Netlify**, **Neon**, **Cloudflare**, **Fly**, **Render**,\n**Sentry**, **Upstash**, **MongoDB Atlas**, and **Datadog**.\n\n---\n\n## Proof\n\nTested on production repositories. Patterns found and fixed across repositories\nlike `my-app`, `web-app`, and `api-service`:\n\n- **Redundant CI triggers.** A workflow wired to both `push` and `pull_request`\n  on the same branch runs CI twice per commit. Dropping the redundant trigger\n  halves runner-minute consumption for every push.\n- **Missing timeouts.** Jobs without `timeout-minutes` burn minutes up to\n  GitHub's 6-hour cap on hung runs. Adding a sane timeout is a one-line fix with\n  no functional impact.\n- **Missing concurrency cancellation.** Without a `concurrency` block, rapid\n  pushes queue up and run sequentially instead of cancelling superseded runs.\n  Adding `cancel-in-progress: true` eliminates the queue.\n- **`paths-ignore` gaps.** Workflows without `paths-ignore` for documentation\n  paths run full CI on commit-message and README edits. Excluding `**.md` and\n  `docs/**` removes a class of runs entirely.\n- **Orphaned preview branches.** A Supabase preview branch left running after a\n  feature ships keeps accruing compute cost each billing cycle.\n\nOn repositories that have accumulated these patterns over time, fixing all of\nthem has reduced observed CI spend by up to 80%. The typical range on\nrepositories never previously optimized is 60–80%. Results vary by workflow\nstructure and push cadence; these are observed, directional outcomes, not a\nguarantee.\n\n<p align=\"center\">\n  <img src=\"assets/chart-before-after-minutes.svg\" alt=\"Redundant CI runs before vs after CostGuard across my-app, web-app, and api-service\" width=\"720\">\n</p>\n\n---\n\n## Using CostGuard\n\nEvery host drives the same read-only engine — reach for it the native way. Each\nblock below is self-contained; use the one for your host.\n\n### Claude Code\n\nThree slash commands plus the full `costguard` skill (scan, providers, registry,\nreport, digest):\n\n- `/costguard-audit` — audit a workspace for CI/cron and cloud-spend waste.\n- `/costguard-fix` — preview or apply the safe in-repo CI fixes (dry-run first).\n- `/costguard-live` — opt-in, consent-gated live billing read for a provider.\n\n### Codex\n\nInvoke the bundled `costguard` skill by name, then say what you want:\n\n- \"Use the costguard skill to audit my-app for CI waste.\"\n- \"With costguard, show a dry-run fix for web-app's workflows.\"\n- \"Run a costguard provider billing check across api-service.\"\n\n### Cursor / Gemini CLI / Cline / Windsurf\n\nInstall the `/costguard` adapter once for your host:\n\n```sh\ncostguard install --target cursor\ncostguard install --target gemini\ncostguard install --target cline\ncostguard install --target windsurf\n```\n\nThen drive it with any `costguard` arguments:\n\n```text\n/costguard audit my-app\n/costguard fix my-app --apply\n```\n\n(If `costguard` is not yet on your PATH, prefix the install command with\n`npx -y -p @costguard/costguard-mcp `.)\n\n### Any MCP host\n\nCopy-paste CostGuard's MCP server into your host's config — no checkout:\n\n```json\n{\n  \"mcpServers\": {\n    \"costguard\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@costguard/costguard-mcp\"],\n      \"env\": {\n        \"GITHUB_TOKEN\": \"…\",\n        \"SUPABASE_ACCESS_TOKEN\": \"…\",\n        \"RAILWAY_TOKEN\": \"…\",\n        \"NETLIFY_AUTH_TOKEN\": \"…\",\n        \"NEON_API_KEY\": \"…\"\n      }\n    }\n  }\n}\n```\n\nEvery token is optional and read-only; a provider with no token is skipped. See\n[Environment variables](#environment-variables) for the full list and aliases.\n\n`npx -y @costguard/costguard-mcp` (no `-p`, no subcommand) starts the MCP\n**server** for this config; `npx -y -p @costguard/costguard-mcp costguard\n<subcommand>` runs the **CLI**.\n\n---\n\n## Environment variables\n\nProvider tokens are read **only** from the process environment or a gitignored\n`.env` in the CostGuard workspace. They are never printed, logged, or committed.\nEach provider module runs only when one of its tokens is present; offline, the\nmodules are fully exercised by fixtures. All tokens are used **read-only**.\n\n| Variable (any one of) | Provider | Used for |\n|-----------------------|----------|----------|\n| `GITHUB_TOKEN` / `GH_TOKEN` | github | Actions usage per repo (read-only billing PAT) |\n| `SUPABASE_ACCESS_TOKEN` / `SUPABASE_TOKEN` | supabase | Projects, compute size, PITR, branches |\n| `RAILWAY_TOKEN` / `RAILWAY_API_TOKEN` | railway | Services, deploys, usage (read-only GraphQL) |\n| `NETLIFY_AUTH_TOKEN` / `NETLIFY_TOKEN` | netlify | Sites, build minutes, bandwidth |\n| `NEON_API_KEY` / `NEON_API_TOKEN` | neon | Projects, branches, compute hours |\n| `VERCEL_TOKEN` / `VERCEL_API_TOKEN` | vercel | Team deploying seats vs deploy activity |\n| `SENTRY_AUTH_TOKEN` / `SENTRY_TOKEN` | sentry | Monthly error events vs plan quota |\n| `UPSTASH_API_KEY` / `UPSTASH_TOKEN` | upstash | Redis DB commands + storage |\n| `ATLAS_API_KEY` / `MONGODB_ATLAS_TOKEN` | atlas | Cluster tiers + data size |\n| `CLOUDFLARE_API_TOKEN` / `CF_API_TOKEN` | cloudflare | R2 buckets, storage, class A/B ops |\n| `FLY_API_TOKEN` / `FLY_ACCESS_TOKEN` | fly | Apps + dedicated IPv4 addresses |\n| `RENDER_API_KEY` / `RENDER_TOKEN` | render | Service instance plans |\n| `DD_API_KEY` / `DATADOG_API_KEY` | datadog | Enables the module (declaration-only; APM host counts read from config) |\n| `COSTGUARD_DIGEST_WEBHOOK` | — | Optional `digest --post` destination (inert in this build) |\n\nUse `providers --check` to confirm which tokens the environment exposes without\nrevealing any value.\n\n---\n\n## Provider modules\n\nCostGuard ships **thirteen** read-only, opt-in provider modules, and the roster\nis actively expanding. Each reads live billed resources, reconciles them against\nthe registry `active{}` allowlist, and emits `orphaned` and `over-provisioned`\nfindings with a best-effort `$/mo`.\n\n| Module | Reads | Flags |\n|--------|-------|-------|\n| **github** | Actions usage per repo | top minute-burners; repos over budget |\n| **supabase** | Projects, compute size, PITR/add-ons, branches | running preview branches; compute/PITR drift vs registry |\n| **railway** | Services, deploys, usage (read-only GraphQL queries) | idle services; deploys never torn down |\n| **netlify** | Sites, build minutes, bandwidth | build-minute spend; runaway bandwidth |\n| **neon** | Projects, branches, compute hours | idle branches; orphaned (defunct but billed) projects |\n| **vercel** | Team deploying seats vs deploy activity | idle paid deploying seats |\n| **sentry** | Monthly error events | error-event overage vs plan quota |\n| **upstash** | Redis DB commands + storage | pay-as-you-go cost above a fixed plan |\n| **atlas** | Cluster tiers + data size | oversized cluster for its data |\n| **cloudflare** | R2 buckets, storage, class A/B ops | operation-heavy R2 spend |\n| **fly** | Apps + dedicated IPv4 addresses | dedicated IPv4 on non-critical apps |\n| **render** | Service instance plans | oversized instance for its environment |\n| **datadog** | APM host counts (declared in config) | excess provisioned APM hosts |\n\nAll live provider access is HTTP `GET`; the railway module uses GraphQL\n**queries** only, guarded against mutations. The datadog module is\ndeclaration-only — it reconciles operator-declared host counts offline and makes\nno network call. No module ever issues a write or delete call. A module\nactivates only when its token (above) is present; otherwise it is skipped.\n\nMore providers are on the way — coverage is expanding as new billing surfaces are\nresearched and sourced.\n\n---\n\n## Security / read-only posture\n\nCostGuard is built to be safe to run anywhere, including on a schedule:\n\n- **Read-only provider access only.** No write or mutating API call is ever issued. Provider tokens are read-only and are never printed, logged, or committed.\n- **Secrets stay out of the repo.** Tokens are read from the environment or a gitignored `.env*` only. `providers --check` reports presence by variable name, never by value.\n- **The static half needs no credentials.** `audit` (without `--providers`) and `scan` read only local files and are always safe to run.\n- **`fix` is in-repo and dry-run by default.** It edits only `.github/workflows/*` files in the target workspace, never provider or cloud state, and writes nothing until `--apply`.\n- **Outward actions are inert and gated.** `fix --open-pr` and `digest --post` refuse to act without an explicit opt-in flag *and* the matching credential, and even then perform no git push or network post in this build.\n\n---\n\n## How workspaces.json works\n\n`workspaces.json` is the registry of projects CostGuard tracks. `registry --init`\nscans `workspacesRoot` (default: `~/Workspaces`) and writes a fresh file with\nauto-detected `providers` arrays (GitHub, Netlify, Supabase, etc.) and blank\n`active{}` blocks. A starter [`workspaces.example.json`](workspaces.example.json)\nships with this repo.\n\n```json\n{\n  \"root\": \"~/Workspaces\",\n  \"workspaces\": {\n    \"my-app\": {\n      \"providers\": [\"github\", \"netlify\"],\n      \"active\": {}\n    }\n  }\n}\n```\n\nThe `active{}` block is the allowlist used by the provider checks: any live\nresource not listed there is flagged as **orphaned**, and any resource larger or\nmore capable than declared is flagged as **over-provisioned**. Leave it empty if\nyou only run the static half; the provider modules then have nothing to reconcile\nagainst.\n\n---\n\n## Configuration\n\nCreate `costguard.config.json` in the project root to override defaults:\n\n```json\n{\n  \"workspacesRoot\": \"~/Workspaces\",\n  \"defaults\": {\n    \"cronThresholdMinutes\": 15,\n    \"ciMinuteRate\": 0.008,\n    \"assumedPushesPerDay\": 10,\n    \"assumedMinutesPerRun\": 5\n  },\n  \"perWorkspace\": {\n    \"my-app\": {\n      \"cronThresholdMinutes\": 30\n    }\n  }\n}\n```\n\n| Key | Default | Description |\n|-----|---------|-------------|\n| `cronThresholdMinutes` | `15` | Crons running more often than this threshold are flagged |\n| `ciMinuteRate` | `0.008` | USD per runner-minute (GitHub-hosted Linux) |\n| `assumedPushesPerDay` | `10` | Estimated daily push cadence for cost projection |\n| `assumedMinutesPerRun` | `5` | Assumed wasted minutes per redundant CI run |\n\nPer-workspace overrides in `perWorkspace` merge on top of `defaults`.\n\n---\n\n## Scheduler template\n\nA monthly digest can be wired to GitHub Actions via the documented, **inert**\nscheduler template `templates/costguard-digest.yml`.\n\n- It lives under `templates/` — **not** `.github/workflows/` — so it never runs automatically and is not enabled by this project.\n- **To activate:** a human copies it into `.github/workflows/` in the target repo and supplies the required secrets (e.g. `COSTGUARD_DIGEST_WEBHOOK`).\n- **To roll back:** delete the copy from `.github/workflows/`.\n\nActivating the template is a deliberate human action outside CostGuard's own runtime.\n\n---\n\n## CLI reference\n\nThese flags apply to the `costguard` CLI, available via `npm i -g @costguard/costguard-mcp` or `npx -y -p @costguard/costguard-mcp costguard <subcommand>`.\n\nAll commands operate on the `workspaces.json` registry in the project root.\nWorkspace selection is by directory name; `--all` selects every registered\nworkspace. Examples use the global `costguard` command; from a checkout you can\nequivalently run `node dist/cli/index.js <command>`.\n\n### audit\n\nRun the static CI/cron audit, optionally adding read-only provider billing\nchecks, and print a report to stdout.\n\n```sh\n# Audit a single workspace (static checks only)\ncostguard audit my-app\n\n# Audit everything at once\ncostguard audit --all\n\n# CI-minutes check only\ncostguard audit my-app --ci-only\n\n# Cron check only, JSON output\ncostguard audit my-app --crons-only --json\n\n# Add provider billing checks for specific providers (only those whose token is present)\ncostguard audit --all --providers github,supabase\n\n# Add provider checks for every provider whose token is present\ncostguard audit --all --providers all\n```\n\n| Option | Effect |\n|--------|--------|\n| `--all` | Audit all registered workspaces |\n| `--ci-only` | Run only the CI-minute checks |\n| `--crons-only` | Run only the cron-frequency checks |\n| `--site` | Also run read-only live-site checks for workspaces whose registry entry has a `site` URL (see [site](#site)) |\n| `--substitutions` | Add cross-tool `<provider>/cheaper-alternative` suggestions (e.g. a static Vercel/Netlify Pro site → Cloudflare Pages), each with a sourced saving, migration effort, and lock-in caveat |\n| `--providers <list>` | Add read-only provider billing checks. Comma-separated ids (`github,supabase,railway,netlify,neon`) or `all`. A provider is only contacted when its token is present (see [Environment variables](#environment-variables)); others are silently skipped. |\n| `--json` | Emit JSON instead of Markdown |\n\n### scan\n\nStatic-only audit across all workspaces. A convenience alias intended for a\nsingle catch-all CI step; it never touches provider credentials.\n\n```sh\ncostguard scan\ncostguard scan --ci      # CI minutes only\ncostguard scan --crons   # Cron schedules only\n```\n\n### providers\n\nReport which provider tokens are present in the environment, by\nenvironment-variable **name** only. Secret values are never read into output,\nprinted, or logged.\n\n```sh\ncostguard providers --check\n```\n\n`--check` is the default action.\n\n### discover\n\nDetect which providers a repo actually uses — from config files, `package.json`\ndependencies, and environment-variable **names** (never values, never secrets).\nCovers all 13 wired providers plus inngest, so you don't hand-edit the registry.\n\n```sh\n# List detected providers + the evidence for each (default dir: .)\ncostguard discover ./my-app\n\n# JSON: { dir, providers, detections }\ncostguard discover ./my-app --json\n\n# Union-merge detected providers into ./workspaces.json (non-destructive)\ncostguard discover ./my-app --write\n```\n\n`--write` preserves any existing providers, the `active{}` block, and every other\nworkspace; it only adds newly detected providers for `basename(dir)`.\n\n### site\n\nAudit a **live URL** for cost-relevant waste — read-only and GET-only (no\nbrowser, no form submit, no credential replay). It flags transfer weight,\noversized images, missing compression, weak cache headers, and render-blocking\nscripts. The page's `$/mo` headline is the single `site/transfer-weight` line\n(sourced when the host bills transfer — Vercel/Netlify — or an explicit `$0`\nperformance note when it doesn't, e.g. Cloudflare Pages static / unknown host;\nnever a fabricated number). Per-asset findings (`oversized-image`,\n`missing-compression`) report their dollar share in the `detail` text and carry\n`estMonthlyUsd: 0` so the headline isn't double-counted. A `$0` performance-only\npage never raises a `high` finding, so it never fails CI on cost alone.\n\n```sh\ncostguard site https://example.com\ncostguard site https://example.com --json\n```\n\nUse `audit --site` to run the same checks for every workspace whose\n`workspaces.json` entry declares a `site` URL.\n\n### registry\n\nManage the workspace registry (`workspaces.json`).\n\n```sh\n# List all registered workspaces and detected providers\ncostguard registry --list\n\n# Validate the registry against the filesystem\ncostguard registry --validate\n\n# Scan ~/Workspaces and write a fresh workspaces.json\ncostguard registry --init\n```\n\n`--list` is the default when no option is given.\n\n### report\n\nRe-render the most recent saved audit run without re-scanning.\n\n```sh\ncostguard report --last\ncostguard report --last --json\n```\n\n### fix\n\nDeterministically auto-fix the safe CI rules in-repo: `paths-ignore`,\n`concurrency`, and `timeout-minutes`. It only edits `.github/workflows/*` files\ninside the target workspace and **never** touches provider or cloud state. It\n**defaults to a dry run** — it prints a unified diff and writes nothing until you\npass `--apply`.\n\n```sh\n# Dry run: print the unified diff for a workspace, write nothing (default)\ncostguard fix my-app\n\n# Dry run across all workspaces\ncostguard fix --all\n\n# Write the edits to disk (idempotent — safe to re-run)\ncostguard fix my-app --apply\n\n# Write local PR artifacts (branch name, patch, PR body) under ~/.costguard/pr/\ncostguard fix my-app --pr\n```\n\n| Option | Effect |\n|--------|--------|\n| `--all` | Fix all registered workspaces |\n| `--apply` | Write the edits to disk. Idempotent. Omit for a dry-run preview. |\n| `--pr` | Write local PR artifacts (`branch.txt`, `fix.patch`, `pr-body.md`) under `~/.costguard/pr/<workspace>/`. No network or git action. |\n| `--open-pr` | **Gated and inert.** Refuses unless **both** the `--open-pr` flag and a non-empty `GITHUB_TOKEN` are present, and even then performs **no** git branch, commit, or push — this build is dry-run only. |\n\n### digest\n\nProduce a concise **monthly** summary — total `$/mo`, a per-provider breakdown,\nand the top findings — distinct from the full `report`. It **defaults to printing\nto stdout** (a dry run). The digest deliberately omits per-finding `detail`/`fix`\ntext; run `report --last` for the full breakdown.\n\n```sh\n# Print the monthly digest to stdout (default)\ncostguard digest --all\n\n# Render from the last saved run\ncostguard digest --last\n\n# JSON output\ncostguard digest --all --json\n\n# Write it to a local file instead of stdout\ncostguard digest --all --out digest-2026-05.md\n```\n\n| Option | Effect |\n|--------|--------|\n| `--all` | Build the digest across all registered workspaces |\n| `--last` | Render the digest from the last saved run instead of re-scanning |\n| `--json` | Emit JSON instead of Markdown |\n| `--out <file>` | Write the digest to a local file instead of stdout |\n| `--post` | **Gated and inert.** Requires **both** the `--post` flag and a `COSTGUARD_DIGEST_WEBHOOK` env var; even then it performs **no** network post. It only reports the message it *would* post. |\n\n---\n\n## Exit codes\n\n| Code | Meaning |\n|------|---------|\n| `0` | All checks passed (or only INFO/WARN findings) |\n| `1` | At least one HIGH severity finding (CI gate signal) |\n| `1` | Error loading registry, config, or invalid arguments |\n\n---\n\n## From source\n\nThe plugin and npm installs are prebuilt — you only need a build when developing\nfrom a checkout:\n\n```sh\npnpm install\npnpm build      # emits dist/cli/index.js and dist/mcp/server.js\npnpm test\n```\n\n### Local checks (run CI without GitHub minutes)\n\nGitHub Actions is metered on private repos, so CI is gated to run only when the\nrepo is public or via manual dispatch. Run the exact same checks locally instead:\n\n```sh\npnpm verify     # typecheck + lint + test + check:dist (mirrors .github/workflows/ci.yml)\n```\n\nEnable the pre-push hook to run `pnpm verify` automatically before every push:\n\n```sh\ngit config core.hooksPath .githooks   # once per clone\ngit push --no-verify                  # bypass for a single push (e.g. docs-only)\n```\n\n#### Run the real workflow in Docker (act)\n\nTo execute the actual `ci.yml` locally in a container — the closest thing to\nGitHub's runner without spending minutes — use [`act`](https://github.com/nektos/act)\nwith Docker Desktop running:\n\n```sh\ngh extension install nektos/gh-act    # once per machine\npnpm ci:docker                        # runs the ubuntu-latest leg via .actrc\n```\n\n`act` runs Linux containers only, so it covers the **ubuntu-latest** matrix leg;\nthe **windows-latest** leg is covered by `pnpm verify` on the host. The first run\npulls the runner image (~1GB), then caches it.\n\n---\n\n## Links\n\n- **GitHub:** https://github.com/mbanderas/costguard\n- **Issues:** https://github.com/mbanderas/costguard/issues\n- **License:** [MIT](LICENSE)\n","readmeFilename":"README.md","_rev":"1-9a62e9b339ef861da1b2790a80c82729"}