Skip to content
Back to skills

Code Complexity Stats Pr

ASecurity

Add a GitHub Actions workflow that posts code-size and cost statistics — lines of code, per-language breakdown, complexity, and a COCOMO "what would this cost to build" estimate — as a sticky comment on every pull request, using scc. Use when you want a per-PR code-stats or "worth of the codebase" comment, to show LOC / language breakdown or an estimated development cost/effort on PRs, to set up scc (Sloc Cloc and Code) in CI, to post or upsert a single self-updating bot comment from GitHub A...

  • 3 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 5, 2026
ai-agentsrustgogitapisecurity

Works with

  • api

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned September 5, 2026

npx -y skills add stealth-factory/skills --skill code-complexity-stats-pr --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Code Complexity Stats Pr?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Code Complexity Stats Pr
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/stealth-factory-code-complexity-stats-pr/badge)](https://www.skillsdirectory.com/skills/stealth-factory-code-complexity-stats-pr)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: code-complexity-stats-pr
description: Add a GitHub Actions workflow that posts code-size and cost statistics — lines of code, per-language breakdown, complexity, and a COCOMO "what would this cost to build" estimate — as a sticky comment on every pull request, using scc. Use when you want a per-PR code-stats or "worth of the codebase" comment, to show LOC / language breakdown or an estimated development cost/effort on PRs, to set up scc (Sloc Cloc and Code) in CI, to post or upsert a single self-updating bot comment from GitHub Actions, or to change the COCOMO salary/currency. Covers fork-PR token limits, runner architecture, version pinning, and comment pagination.
metadata:
  author: stealth-factory
  co-author: wiiiimm
  version: "1.2.0"
---

# Code complexity / cost stats on every PR

A GitHub Actions workflow that runs [`scc`](https://github.com/boyter/scc)
(Sloc, Cloc and Code) over the repo on each pull request and posts the results —
including a **COCOMO** estimated cost/effort to build the codebase — as a **single
sticky comment** that updates in place on every push. Drop-in workflow:
[`templates/code-complexity.yml`](./templates/code-complexity.yml).

## What you get

`scc` prints a per-language table (files, lines, code, comments, blanks,
complexity) plus, with `--avg-wage`, a **COCOMO** block: estimated person-months,
schedule, people, and a **dollar cost to develop**. The workflow wraps that in a
fenced block and posts it as a PR comment titled *📊 Code Complexity Analysis*.

It reports the **whole codebase at the PR's head**, not the diff — it's a
"what's this project worth / how big it is" signal, not a per-PR delta.

## Install

Copy [`templates/code-complexity.yml`](./templates/code-complexity.yml) to
`.github/workflows/code-complexity.yml`. It works as-is on `ubuntu-latest`; the
only thing you'll likely change is the `AVG_WAGE` / `WAGE_LABEL` workflow env (see Customise).

## How it works (the parts that matter)

- **Trigger:** `pull_request: [opened, synchronize, reopened]` — runs on open and
  every push. Kept as its **own workflow** so it always runs even when other
  workflows honour a `[skip ci]`-style marker; these stats are informational.
- **Permissions:** a PR comment is posted via the *Issues* API, so
  `pull-requests: write` is what actually authorises the create/update;
  `issues: write` is included belt-and-suspenders. (Both are in the template.)
- **Sticky comment:** the body starts with a hidden marker
  `<!-- code-complexity -->`. The script lists existing comments, finds the one
  with that marker, and **updates it** (else creates one) — so a PR keeps exactly
  one stats comment that refreshes instead of stacking new ones each push.
- **Concurrency:** `cancel-in-progress: true` keyed on the **PR number**
  (`github.event.pull_request.number`) — a new push kills the in-flight run so you
  don't race two comment updates. Keyed on the number, not `head_ref`, so two
  forks sharing a branch name can't cancel each other.
- **COCOMO cost:** `scc --avg-wage <annual>` drives the cost figure. The number is
  unitless to scc — it's read in *your* currency. The template defines `AVG_WAGE`
  (`360000`, HKD 30,000/month) and `WAGE_LABEL` once as workflow `env`, so the
  number scc uses and the label in the comment can't drift — change the salary in
  one place.

## Customise

| Want to… | Change |
| --- | --- |
| Use a different currency / salary | the `AVG_WAGE` and `WAGE_LABEL` workflow `env` (one place — the comment label reads `WAGE_LABEL`) |
| Exclude more build/generated dirs | `--exclude-dir` list (comma-separated). scc honours `.gitignore` by default; this is for output that isn't ignored |
| Pin / upgrade scc | `SCC_VERSION` in the install step |
| Run on ARM runners | swap the tarball to `scc_Linux_arm64.tar.gz` and use an ARM runner (e.g. `ubuntu-24.04-arm`) |
| Count only part of a monorepo | add a path arg to `scc` (e.g. `scc apps/web`) |

## Gotchas

- **Fork PRs can't post the comment.** For PRs from forks, `pull_request` runs
  with a **read-only** token and no repo secrets, so the comment API call would
  403. Declaring `pull-requests: write` does **not** override this — GitHub
  enforces read-only on the token itself for fork-triggered runs. The template
  guards the **whole job** with
  `if: github.event.pull_request.head.repo.full_name == github.repository`, so on
  fork PRs the job **skips cleanly** (green check) instead of failing red — and no
  compute is wasted running scc for a comment that can't post. Options:
  (a) accept that stats only post for same-repo branches (fine for solo/team
  repos — the common case; this is the template default); or (b) split into two
  workflows — compute on `pull_request` (no secrets,
  untrusted code), upload `scc-output.txt` as an artifact, then comment from a
  separate `workflow_run` job that has write access. **Do not** just switch this
  workflow to `pull_request_target`: that runs with a write token in the *base*
  repo context, and checking out + running fork code there is a token-exfiltration
  footgun.
- **Long output is truncated, not failed.** GitHub caps a comment body at 65,536
  characters. Default scc output (a per-language table) is tiny, but `--by-file`
  on a big repo could blow past it, which *would* 422 the step — so the template
  trims to ~64k with a "truncated" note and the comment still posts.
- **Pin scc; don't track `latest`.** A `latest` download can change scc's output
  format and silently reshape every PR comment. The template pins `SCC_VERSION`
  **and** verifies the tarball against a pinned `SCC_SHA256` (`sha256sum -c`)
  before running it, so a swapped/compromised release asset fails the run instead
  of executing in CI. When you bump the version — or switch to the arm64 asset —
  update the checksum from that release's `checksums.txt`.
- **Match the tarball to the runner arch.** The release asset is arch-specific
  (`scc_Linux_x86_64.tar.gz` vs `_arm64`). The wrong one fails to run.
- **Paginate when finding the sticky comment.** A busy PR can have more comments
  than one API page; without pagination, the marker comment on a later page is
  missed, and you get duplicates. The template uses `github.paginate(...)` and
  matches the marker with `startsWith` (not `includes`) so a human comment that
  merely quotes the marker isn't mistaken for the bot's and overwritten.
- **Token: `GH_TOKEN || github.token`.** The template prefers a `GH_TOKEN` secret
  (a PAT/bot you already use) and falls back to **`github.token`** — the canonical
  reference to the built-in `GITHUB_TOKEN`. Prefer `github.token` over
  `secrets.GITHUB_TOKEN`; the built-in token is enough for same-repo comments
  given the permissions above.
- **COCOMO is illustrative.** It's the basic COCOMO model (COCOMO I, Organic mode)
  on LOC — a fun, *relative* signal of size/effort, not a real valuation. Don't
  quote it as the literal worth of the code.

## Provenance

Generalised from the working `code-complexity.yml` used in production repos
(a production app, a production monorepo): same scc + COCOMO + sticky-comment approach, hardened
here with version pinning + checksum verification, `persist-credentials: false`,
comment pagination, a portable `ubuntu-latest` runner, and the fork-PR security
note.

Files in this skill

  • SKILL.md7.2 KB
  • templates/code-complexity.yml5.5 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.