SOC2 CC6.3 requires quarterly access reviews. Every engineering leader and security engineer at a SOC2/ISO 27001 company knows the pain: producing evidence by clicking through GitHub's web UI, repo by repo, for 100+ repositories.
vcs-access-review queries your GitHub org's full member roster — roles, team memberships, repo-level admin grants, and last-activity proxy — and renders it as an auditor-ready Markdown, CSV, or JSON report. One command, once per quarter.
No SaaS subscription. No connector setup. No enterprise pricing. Just npx and a token.
- No TypeScript CLI covers this use case. Zero results across GitHub and npm.
- GitHub's own
ghec-audit-log-cliwas archived October 2024. It only queried audit event logs — never addressed member/role access reviews. No replacement has emerged. - Commercial solutions are overkill. ConductorOne and Veza are full access governance platforms at $10-30/user/month. You don't need an enterprise SaaS to answer "who has admin access to what?" once per quarter.
- Manual review breaks at scale. 100+ repos is the norm for any team past Series A. The GitHub Community is asking for this — the accepted answer is raw API calls with no package wrapper.
npm install -g vcs-access-reviewOr run directly:
npx vcs-access-review run --org your-org --token ghp_...export GITHUB_TOKEN="ghp_..."
vcs-access-review run --org your-orgvcs-access-review run --org your-workspace --provider bitbucket --token "user@example.com:app_password"This produces a file like access-review-your-org-2026-03-12.md in the current directory.
| Flag | Description | Default |
|---|---|---|
--org <org> |
GitHub org or Bitbucket workspace | required |
--provider <provider> |
VCS provider: github, bitbucket |
github |
--token <token> |
Auth token (see below) | -- |
--format <fmt> |
Output format: md, csv, json |
md |
--since <days> |
Inactivity threshold in days | 90 |
--output <dir> |
Output directory | . |
GitHub: Pass a PAT via --token or set the GITHUB_TOKEN env var.
Bitbucket Cloud: Pass --token username:app_password or set the BITBUCKET_TOKEN env var in the same format.
Required Bitbucket app password scopes: account, repository:admin, team (for groups).
# GitHub — Markdown report (default)
vcs-access-review run --org acme-corp
# GitHub — CSV for upload to your GRC tool
vcs-access-review run --org acme-corp --format csv
# GitHub — JSON for programmatic use
vcs-access-review run --org acme-corp --format json
# GitHub — Flag anyone inactive for 30+ days
vcs-access-review run --org acme-corp --since 30
# GitHub — Write to a reports directory
vcs-access-review run --org acme-corp --output ./reports
# Bitbucket Cloud — using --token
vcs-access-review run --org my-workspace --provider bitbucket --token "user@example.com:app_password"
# Bitbucket Cloud — using env var
export BITBUCKET_TOKEN="user@example.com:app_password"
vcs-access-review run --org my-workspace --provider bitbucket
For every member in your org/workspace:
- Workspace role —
ownerormember - Group/team memberships — every team and their role within it
- Direct admin repos — repos where the user has
adminaccess granted directly (not inherited via team) - Last activity — days since last activity (GitHub: public events; Bitbucket:
last_accessedfrom permissions API)
| Column | Description |
|---|---|
| Username | GitHub login |
| Workspace Role | owner or member |
| Groups/Teams | Team memberships with role (maintainer/member) |
| Admin Repos | Repos where user has direct admin access |
| Last Active (days) | Days since last public event, or unknown |
| Flagged | YES if the account needs review |
Members are automatically flagged for auditor attention when any of the following are true:
- Org owner — elevated privilege across the entire org
- Direct admin on repos — admin access granted directly, with no team justification
- Inactive — no public activity within the
--sincethreshold (default 90 days), or no activity data available
GitHub PAT:
read:org— read org members, teams, and membershipsrepo— read repo collaborators and permissions
Bitbucket app password:
account— read workspace members and permissionsrepository:admin— read repo-level permissionsteam— read groups (v1 API)
The CLI is built around a provider interface that makes multi-platform support straightforward:
interface AccessReviewProvider {
name: 'github' | 'bitbucket';
getMembers(workspace: string, token: string): Promise<WorkspaceMember[]>;
}The CLI, output formatting, and report structure are identical regardless of provider — only the API implementation differs.
- v0.1 — GitHub provider
- v0.2 — Bitbucket Cloud provider (current)
- v0.3 — Comparison diffs between quarterly runs ("who was added/removed?")
MIT