Public record
Software health reportschema 0.27.0 · metrics 1.13.0 · 2026-07-29 21:23 UTC

zach-source / ccswitch

Multi-account switcher and usage monitor for Claude Code

GoMIT★ 1 star⑂ 0 forkssince Apr 2026View on GitHub ↗

zach-source/ccswitch holds a health index of 45 out of 100, placing it in the At risk band. It scores highest on Vitality (75/100) and lowest on Community & Adoption (24/100). It was last updated 3 days ago. A single contributor accounts for most of its recent work.

45
overall / 100
At risk

Software health index

Metrics are grouped into weighted categories on one standardized 1–100 scale. Overall starts as their weighted mean; when public evidence triggers the High-Risk Jurisdiction Policy, the rating is adjusted and receives an At risk ceiling of 49. AI Readiness sits outside the overall score.

45
Excellent85-100Exemplary; meets essentially all checked criteria
Good70-84Healthy; minor gaps
Moderate50-69Acceptable with notable gaps; review recommended
At risk30-49Significant weaknesses; adoption warrants caution
Critical1-29Severe problems (abandoned, single-maintainer, no hygiene)
VitalityCommunity &AdoptionSustainability &GovernanceEngineeringQualitySecurityAI Readiness

Score profile

Each axis is a category. The shape matters more than the average — a healthy subject fills the whole shape, while a spike-and-crater profile means strength in one dimension is masking risk in another.

Ownership

Zachary TaylorPersonal account
12 followers90 public repossince Mar 2020Ripple

This repository is owned by a personal account. A single-owner project carries more continuity risk than an organization-backed one.

Package ecosystems

RegistryPackageVersionDownloads / moVersionsLast publish
Gogithub.com/zach-source/ccswitchv1.6.0-17114 days ago

Metrics by category

Vitality

Is the project alive — is code being written and are releases shipping?

75Good · 22% of overall
How it's scored
36/36Push recency — last push 3 days ago
6.9/36Commit cadence — 10/52 weeks with commits
16/18Commit volume — 60 commits in the last year
10/10OpenSSF Scorecard: Maintained — 30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10
Inputs used
commits_last_year60
human_commit_share1
days_since_last_push3
active_weeks_last_year10
How it's scored
27/27Ships releases — 1 releases published
36/36Release recency — latest release 3 days ago
12.6/27Release cadence — cadence unknown (single release)
0/10OpenSSF Scorecard: Signed-Releases — no data
Inputs used
releases_count1
latest_release_tagv2.8.0
releases_from_tagsno
days_since_latest_release3
mean_days_between_releases
Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.

Community & Adoption

Does the project have users, downloads, attention, and a welcoming setup for contributors?

24Critical · 18% of overall
How it's scored
0/60Stars — 1 stars
0/25Forks — 0 forks
0/15Watchers — 0 watchers
Inputs used
forks0
stars1
watchers0
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
How it's scored
22.5/22.5README
22.5/22.5License — recognized license (MIT)
0/18CONTRIBUTING guide
0/13.5Code of conduct
0/7.2Issue template
0/6.3PR template
Inputs used
has_readmeyes
has_licenseyes
has_contributingno
has_issue_templateno
has_code_of_conductno
has_pull_request_templateno

Sustainability & Governance

Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?

46At risk · 24% of overall
How it's scored
9/54Bus factor — 1 contributor(s) cover half of all commits
0/22.5Commit distribution — top contributor authored 100% of commits
1.4/13.5Contributor breadth — 1 contributors
3/10OpenSSF Scorecard: Contributors — project has 1 contributing companies or organizations -- score normalized to 3
Inputs used
bus_factor1
contributors_sampled1
top_contributor_share1
How it's scored
0/46.8Issue resolution — 0% of issues closed
35.5/38.3PR acceptance — 13/14 decided PRs merged
0/15OpenSSF Scorecard: Code-Review — Found 0/16 approved changesets -- score normalized to 0
Inputs used
merged_prs13
open_issues1
closed_issues0
issue_closed_ratio0
closed_unmerged_prs1
How it's scored
10/30Ownership backing — personal (user) account
0/20Verified domain — not applicable to user accounts
8/25Owner reach — 12 followers of zach-source
25/25Track record — 90 public repos, account ~6 yr old
Inputs used
followers12
owner_typeUser
is_verified
owner_loginzach-source
public_repos90
account_age_days2,336
Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.
How it's scored
25/25Published & resolvable — 1 package(s) on go
35/35Publish recency — latest publish 114 days ago
20/20Version history — 17 published versions
20/20Not deprecated — active, not deprecated or yanked
Inputs used
packagesgithub.com/zach-source/ccswitch
ecosystemsgo
any_deprecatedno
min_days_since_publish114

Engineering Quality

Are baseline engineering and documentation practices in place?

44At risk · 20% of overall
How it's scored
0/24CI workflows
24/24Tests present
0/16Linter config
0/9.6Pre-commit hooks
0/6.4.editorconfig
0/20OpenSSF Scorecard: CI-Tests — 0 out of 13 merged PRs checked by a CI test -- score normalized to 0
Inputs used
has_cino
has_testsyes
has_editorconfigno
has_linter_configno
has_precommit_configno
How it's scored
30/30README
25/25Documentation directory
0/15Documentation / homepage site
10/10Repository description
0/10Topics
10/10Wiki
Inputs used
topics
has_wikiyes
homepage
has_readmeyes
has_docs_diryes
has_descriptionyes

Security

Are visible security and supply-chain practices strong, without unresolved high-risk jurisdiction exposure?

29Critical · 16% of overall
How it's scored
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — branch protection not enabled on development/release branches
0/2.5CI-Tests — 0 out of 13 merged PRs checked by a CI test -- score normalized to 0
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/16 approved changesets -- score normalized to 0
0.8/2.5Contributors — project has 1 contributing companies or organizations -- score normalized to 3
0/10Dangerous-Workflow — no data
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5License — license file detected
7.5/7.5Maintained — 30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10
0/5Packaging — no data
0/5Pinned-Dependencies — no data
0/5SAST — SAST tool is not run on all commits -- score normalized to 0
2/5Security-Policy — security policy file detected
0/7.5Signed-Releases — no data
0/7.5Token-Permissions — no data
0/7.5Vulnerabilities — 25 existing vulnerabilities detected
Inputs used
sourceopenssf_scorecard
checks_evaluated13
scorecard_versionv5.5.0
checks_inconclusive5
scorecard_aggregate2.9
Excluded from scoring (no data or not applicable): dangerous_workflow, packaging, pinned_dependencies, signed_releases, token_permissions. Remaining weights renormalized.

AI Readiness

How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score.

64Moderate · 0% of overall
How it's scored
0/45Agent instructions — no CLAUDE.md / AGENTS.md / editor rules
0/15Machine-readable docs (llms.txt)
40/40Legible commit history — 60 of 60 human commits state their intent (structured subject or explanatory body)
Inputs used
has_llms_txtno
legible_history_share1
agent_instruction_files
agent_instruction_max_bytes
How it's scored
18/18One-command bootstrap — Makefile
22/22Automated tests
0/11Lint / format config
11/11Static type checking — Go (statically typed)
10/10Reproducible environment — Nix, lockfile
0/10Demonstrated agent practice — no agent-authored commits among the last 60
0/8Automated maintenance — no automated dependency updates observed
0/10OpenSSF Scorecard: Pinned-Dependencies — no data
Inputs used
has_nixyes
has_testsyes
lockfilesgo.sum
has_dockerfileno
typed_languageyes
bootstrap_filesMakefile
has_devcontainerno
has_linter_configno
typecheck_configs
agent_commit_share0
toolchain_manifestsgo.mod
dependency_bot_commit_share0
Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Pinned-Dependencies. Remaining weights renormalized.
How it's scored
45/45Type-checkable code — Go (statically typed)
55/55Manageable file sizes — 0/67 source files over 60KB
Inputs used
primary_languageGo
largest_source_bytes18,504
source_files_sampled67
oversized_source_files0

Key facts

1GitHub stars
1contributors
60commits, last 12 months
3days since last push
1releases
1bus factor
1open issues
Gopackage ecosystems

Data collection warnings

  • Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token
  • GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

More detail

OpenSSF Scorecard 2.9 / 10
2.9aggregate

Independent, tool-agnostic security assessment from the open-source OpenSSF Scorecard. Each check rewards a security practice, not a specific vendor's tool. Checks Scorecard could not determine are marked n/a and excluded from the security score (never counted as zero).Scorecard v5.5.0 · 2026-07-29 21:23 UTC

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
0CI-Tests0 out of 13 merged PRs checked by a CI test -- score normalized to 0
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/16 approved changesets -- score normalized to 0
3Contributorsproject has 1 contributing companies or organizations -- score normalized to 3
n/aDangerous-Workflowno workflows found
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
10Maintained30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10
n/aPackagingpackaging workflow not detected
n/aPinned-Dependenciesno dependencies found
0SASTSAST tool is not run on all commits -- score normalized to 0
4Security-Policysecurity policy file detected
n/aSigned-Releasesno releases found
n/aToken-PermissionsNo tokens found
0Vulnerabilities25 existing vulnerabilities detected
Direct dependencies 5
RegistryPackageVersion constraintManifest
Gogithub.com/hashicorp/vault/apiv1.23.0go.mod
Gogithub.com/keybase/go-keychainv0.0.1go.mod
Gogithub.com/pelletier/go-toml/v2v2.3.0go.mod
Gogithub.com/spf13/cobrav1.10.2go.mod
Gogolang.org/x/termv0.42.0go.mod
All dependencies not collected

The resolved dependency set could not be collected for this report: GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

Raw JSON report machine-readable
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 321,
      "has_wiki": true,
      "homepage": null,
      "languages": {
        "Go": 327162,
        "Nix": 2007,
        "Shell": 8093,
        "Makefile": 1132
      },
      "pushed_at": "2026-07-26T18:34:23Z",
      "created_at": "2026-04-05T18:21:04Z",
      "owner_type": "User",
      "updated_at": "2026-07-26T18:34:27Z",
      "description": "Multi-account switcher and usage monitor for Claude Code",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "MIT",
      "default_branch": "main",
      "license_spdx_raw": "MIT",
      "primary_language": "Go",
      "significant_languages": [
        "Go"
      ]
    },
    "owner": {
      "blog": null,
      "name": "Zachary Taylor",
      "type": "User",
      "login": "zach-source",
      "company": "Ripple",
      "location": null,
      "followers": 12,
      "avatar_url": "https://avatars.githubusercontent.com/u/61884887?v=4",
      "created_at": "2020-03-06T18:12:56Z",
      "is_verified": null,
      "public_repos": 90,
      "account_age_days": 2336
    },
    "license": {
      "state": "standard",
      "spdx_id": "MIT",
      "raw_spdx": "MIT",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v2.8.0",
          "kind": "minor",
          "published_at": "2026-07-26T18:34:30Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "4406b5ab832cd4c29b6e1a655cd2269a3ce13a80",
          "body": null,
          "is_bot": false,
          "headline": "release: v2.8.0 — browser-free login (login --manual)",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-07-26T18:34:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "027c7ad00f24bd87e62df5f166476efc2ab88dca",
          "body": "login: add --manual, browser-free login (start/finish, returns immediately)",
          "is_bot": false,
          "headline": "Merge pull request #15 from zach-source/manual-login",
          "author_name": "Zachary Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-07-26T18:29:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7438a74bf34508d65e321d7a7d7c600f3ea96886",
          "body": "Replaces the single blocking ManualLogin call with ManualLoginStart\n(prints the URL, returns right away) and ManualLoginFinish (delivers\nthe pasted code, possibly from an entirely separate `ccswitch`\ninvocation/process later on):\n\n  ccswitch login --only <id> --manual                # start\n  ccswit\n[…]\n2.1.220 CLI: start returns\nin under a second with the real URL, and finish (given a deliberately\nwrong code, so no real login ever completes) correctly delivers it and\nsurfaces claude's own rejection.",
          "is_bot": false,
          "headline": "login --manual: split into start/finish so start returns immediately",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-07-26T18:14:16Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b799845b861a7883514dd8df818a1a25fe323e0b",
          "body": "Adds a headless login path that never launches a local browser: it\nprints the OAuth authorize URL for the operator to open on any device\n(phone, another machine, ...) and completes the exchange from the\nresulting \"code#state\" response, supplied either interactively (typed\nor piped on stdin) or non-i\n[…]\nrowser/noopener.go   - InstallNoOpener shim + test\n  internal/refresh/manual.go     - ManualLogin + test (fake-claude harness)\n  internal/cli/refresh.go        - `login --manual`/`--code` flags + test",
          "is_bot": false,
          "headline": "login: add --manual, browser-free login (present URL, paste response)",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-07-26T14:11:15Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e9f1633842d53e65f68cece26d7ad334cab2f3c6",
          "body": "The CLI backend stores credentials as op documents; the Connect backend's\nRead only understands secure-note 'credentials' fields and returns\nErrNotFound for documents. usage-all reads non-active accounts through the\nConnect store, so all of them showed 'no token'. Extend the fallback\n(renamed WriteFallback -> CLIFallback) to retry reads via the op CLI on\nErrNotFound. Connect is still tried first, so the op session is prompted at\nmost once per run and only when needed.",
          "is_bot": false,
          "headline": "onepassword: also fall back reads to op CLI on ErrNotFound (#13)",
          "author_name": "Zachary Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-07-17T19:05:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "44299a77960d3912b9c2d220bdd80cb9afff1192",
          "body": "Connect access tokens have their vault read/write scope fixed at creation.\nA read-only token 403s on login's credential write (HTTP PUT). Wrap the\nConnect backend so Write/Delete retry through the user's full-permission\nop CLI session on a 403; reads stay on Connect. No-op when op is absent.",
          "is_bot": false,
          "headline": "onepassword: fall back to op CLI for writes on Connect 403 (#11)",
          "author_name": "Zachary Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-07-17T18:52:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2378e59e1d62e6377ea9c9e7a8a0c7052280a8ae",
          "body": "Nix builds ccswitch ad-hoc/linker-signed with no stable code identity, so\nmacOS can never persist a keychain 'Always Allow' grant to the binary —\nevery direct Security.framework read re-prompts for the login-keychain\npassword, worse on every rebuild (new store path). Route reads through the\nApple-si\n[…]\n/security instead: one 'Always Allow' for it sticks\nacross ccswitch updates. Secret returns on stdout, never argv, preserving\nthe argv-exposure protection that motivated go-keychain. Writes unchanged.",
          "is_bot": false,
          "headline": "fix(keychain): read via /usr/bin/security so 'Always Allow' persists",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-07-13T01:27:36Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f1b07aaa06def1ba21c0bf560efc433e2ef104e3",
          "body": "- claudelock.go: proper-lockfile-compatible directory locking on\n  ~/.claude.lock and <claude.json>.lock, matching the mkdir/mtime-staleness\n  protocol Claude Code itself uses when refreshing OAuth tokens. performSwitch\n  now holds both locks around the mutation steps (snapshot prior creds, save\n  s\n[…]\na pure, table-tested function\n  (decideAutoSwitch) with no I/O.\n\nAll new logic is covered by table-driven tests (claudelock_test.go,\nautoswitch_test.go). gofmt, go vet, go build, and go test all pass.",
          "is_bot": false,
          "headline": "feat: lockfile-safe swaps, --skip-limited, and autoswitch engine",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-07-13T01:07:53Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4a74b4a16d375001b27c7fea21d6ce6f15dc09c1",
          "body": "…ually swaps (#10)\n\n`performSwitch` only swapped the OAuth token (Keychain `Claude Code-credentials`),\nleaving `~/.claude.json.oauthAccount` pointing at the previous account. Since\nClaude Code reads its displayed identity from that JSON file and the token\nfrom the Keychain, the two halves disagreed \n[…]\n into that account.\n\nTests cover the happy path (verifies oauthAccount is replaced AND unrelated\ntop-level keys survive the merge), the legacy-snapshot fallback path, and\nthe no-identity warning path.",
          "is_bot": false,
          "headline": "fix(switch): pair identity with credentials so the active account act…",
          "author_name": "Zachary Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-05-27T20:27:41Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8043c68295f88e1abd3498225b2d65db2e7a3bb8",
          "body": "fix(refresh): stop orphaning a keychain record on every login",
          "is_bot": false,
          "headline": "Merge pull request #9 from zach-source/fix/login-hashed-slot-orphans",
          "author_name": "Zachary Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-05-20T13:39:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b8b99ce96e89a1428b9632625bd979a795c4a71a",
          "body": "`ccswitch login`/`refresh` run `claude auth login` with CLAUDE_CONFIG_DIR\npointed at a fresh `os.MkdirTemp` dir each time. claude 2.x on macOS\nwrites the captured credential to a per-config hashed keychain service,\n\"Claude Code-credentials-<8hex>\", whose suffix is opaque and effectively\nunique per r\n[…]\n green.\n\nInterface change rippled to the non-darwin stub and the keychain test;\nnew internal/refresh/capture_test.go pins the \"capture returns the hashed\nservice name\" contract the cleanup depends on.",
          "is_bot": false,
          "headline": "fix(refresh): stop orphaning a keychain record on every login",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-05-20T13:39:27Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "bb127376ba019b6a02e438067b6fcba6fc99d9f7",
          "body": "fix(cli): read backups from configured store, active slot from local",
          "is_bot": false,
          "headline": "Merge pull request #8 from zach-source/fix/store-vs-local-backend-split",
          "author_name": "Zachary Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-05-20T07:38:32Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c033284d876295e5fd87f1d5110a8c1b1495409c",
          "body": "Making 1password-cli the default backend exposed a latent conflation of\ntwo backend roles that were identical when the default was keychain:\n\n  - the ACTIVE slot (ActiveCredKey) lives in the local store — the\n    keychain on macOS, which is what `claude` actually reads;\n  - per-account BACKUPS (Back\n[…]\nause it used one backend for both roles.\n\nVerified against the real 1Password vault: usage-all shows all three\naccounts with live utilization; switch-to succeeds. make conformance\ngreen; nix build OK.",
          "is_bot": false,
          "headline": "fix(cli): read backups from the configured store, active slot from local",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-05-20T07:38:17Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "dd55ecbef610be2037fdcf3d1a8f50fd74db973a",
          "body": "feat(1password-cli): cache the op session, one biometric prompt per run",
          "is_bot": false,
          "headline": "Merge pull request #7 from zach-source/feat/op-cli-session-cache",
          "author_name": "Zachary Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-05-20T06:50:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d19697a9661a814f06bb9341e57f0e2a2874af64",
          "body": "…cswitch run\n\nBefore: every Read/Write/Delete invoked `op` afresh, and every `op` call\ntriggered a biometric / desktop-app prompt — `ccswitch login` against\nthree accounts could fire half a dozen approvals in a row.\n\nNow: the CLIBackend runs `op signin --raw` lazily on the first sub-call\nand stashes\n[…]\nvery credential — all one tap.\n\nTest: TestCLIBackend_AccountShorthand pins the URL parsing across the\nformats users actually configure.\n\nmake conformance green: vet + Go tests + 22 bats; nix build OK.",
          "is_bot": false,
          "headline": "feat(1password-cli): cache the op session, one biometric prompt per c…",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-05-20T06:49:54Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0b0235eae25fc9284ac5284f9a9e91c7dbdbb623",
          "body": "feat(backend): add 1password-cli backend (writes via op CLI)",
          "is_bot": false,
          "headline": "Merge pull request #6 from zach-source/feat/op-cli-backend",
          "author_name": "Zachary Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-05-20T04:52:04Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2c7c4c8722f755cc1dca9bdcb1d8d5e0967bb960",
          "body": "…g Connect token perms)\n\nThe Connect HTTP backend's bearer token has read access but lacks\ncreate/update permission on the target vault, so ccswitch login captures\ncredentials correctly and then 1Password returns 403 on the write. Fixing\nthe token's permissions requires admin work in the 1Password U\n[…]\nplied by the 1Password desktop app's\nbiometric integration; if that is not available (headless server),\nkeep using the Connect backend.\n\nmake conformance green: vet + Go tests + 22 bats; nix build OK.",
          "is_bot": false,
          "headline": "feat(backend): add 1password-cli backend (writes via op CLI, bypassin…",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-05-20T04:51:44Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "06f47b627cf11e035038b6cbf402bf5678a0dce1",
          "body": "fix(security): store 1Password Connect secrets in 0600 files, not the keychain",
          "is_bot": false,
          "headline": "Merge pull request #5 from zach-source/fix/op-secrets-to-files",
          "author_name": "Zachary Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-05-19T23:54:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f36d35a9e9889aa182c3b5178134cf11cb3b74a9",
          "body": "… keychain\n\nThe keychain-backed storage of the three Connect/CF Access secrets\nintroduced in the C1 security fix had a structural problem on macOS:\nkeychain ACLs match the calling binary's code identity, and Nix builds\nccswitch into a fresh /nix/store/<hash>/ path on every rebuild. Every\nrebuild mad\n[…]\nrity delete-generic-password -s ccswitch-op-connect-token`\n(and the cf-access-client-{id,secret} variants) if you want a tidy\nkeychain.\n\nmake conformance green: vet + Go tests + 22 bats; nix build OK.",
          "is_bot": false,
          "headline": "fix(security): store 1Password Connect secrets in 0600 files, not the…",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-05-19T23:53:44Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "94cdc2defcb802d45c35beef6053ce227b75795d",
          "body": "feat(login): route OAuth URL into the Chrome profile signed in to the account",
          "is_bot": false,
          "headline": "Merge pull request #4 from zach-source/feat/chrome-profile-router",
          "author_name": "Zachary Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-05-19T23:34:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "22e3eaca38ce2fa6c4ffdef4523a2bc481784406",
          "body": "… account\n\nMulti-account login flows used to require the user to manually switch\nChrome profiles between iterations: claude opens the OAuth URL in\nwhichever Chrome profile happens to be active, which is rarely the one\nsigned in to the account being authorized.\n\nThis adds automatic Chrome-profile rou\n[…]\nn error.\n- renderOpenerScript carries the Chrome binary, --profile-directory\n  flag, both URL patterns, and the system-opener fallback.\n\nmake conformance green: vet + Go tests + 22 bats; nix build OK.",
          "is_bot": false,
          "headline": "feat(login): route OAuth URL into the Chrome profile signed in to the…",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-05-19T23:34:20Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7fc469a56b767252855cb1c36bd0d57c5bc06ff5",
          "body": "fix(refresh): capture claude 2.x's per-CLAUDE_CONFIG_DIR hashed keychain slot",
          "is_bot": false,
          "headline": "Merge pull request #3 from zach-source/fix/claude-hashed-keychain-slot",
          "author_name": "Zachary Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-05-19T23:09:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "186abf908f3b9e0e666018acc015252f0566bab5",
          "body": "…ain slot\n\nFollow-up to the previous fix. Empirical inspection of the user's\nkeychain after `ccswitch login` revealed that claude 2.x, when\nCLAUDE_CONFIG_DIR is set, writes credentials to a *hashed* service slot\nnamed \"Claude Code-credentials-<8hex>\" where the suffix is an opaque\nfunction of the CON\n[…]\nnd_LookupHashedActiveSlot — writes a test slot, asserts\nLookupHashedActiveSlot finds it within the `since` window and skips it\noutside.\n\nmake conformance green: vet + Go tests + 22 bats; nix build OK.",
          "is_bot": false,
          "headline": "fix(refresh): capture claude 2.x's per-CLAUDE_CONFIG_DIR hashed keych…",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-05-19T23:08:32Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "81617373abc54e4d1ed5473dbe604ce02cf91e55",
          "body": "fix(refresh): capture claude 2.x credentials from the keychain on macOS",
          "is_bot": false,
          "headline": "Merge pull request #2 from zach-source/fix/claude-keychain-capture",
          "author_name": "Zachary Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-05-19T21:32:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fe9a0235be5abcf4ec31c183a26b1808052cc08d",
          "body": "Bug report: `ccswitch login` against 3 accounts returned\n\"Interactive login complete: 0/3 accounts refreshed\", logging\n\"no credentials file after claude exit\".\n\nRoot cause: claude 2.x on macOS writes the credential blob directly to\nthe login keychain (\"Claude Code-credentials\") and ignores\nCLAUDE_CO\n[…]\nged; nothing is stored.\n- TestRefreshAll_CapturesFromLocalActiveSlot — same, with an unmodeled\n  field as a raw-bytes regression guard.\n\nmake conformance green: vet + Go tests + 22 bats; nix build OK.",
          "is_bot": false,
          "headline": "fix(refresh): capture claude 2.x credentials from the keychain on macOS",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-05-19T21:31:37Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "df2f3bfa9f9c3854dc9f1659d963d3ae78ff1649",
          "body": "Complete the Go port of ccswitch (v2.0.0)",
          "is_bot": false,
          "headline": "Merge pull request #1 from zach-source/go-port",
          "author_name": "Zachary Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-05-19T20:19:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e65e7bf11ab4c9e1d7e4ae93ee17acd359fd4242",
          "body": "The commands that shell out — login, refresh-all, usage, usage-all,\nuse-zai — were the last untested gap. They resolve claude/ccusage/op by\nname through PATH, so a temp dir of fake executables prepended to PATH\nexercises them with no real tools, network, or browser login.\n\ninternal/cli/external_test\n[…]\ncli/usage.go: the OAuth usage endpoint is now the package var\nanthropicUsageURL purely so the test can point it at httptest.\n\ncli coverage 33% -> 49%. make conformance green: vet + Go tests + 22 bats.",
          "is_bot": false,
          "headline": "test: cover the external-dependency commands with mocked tools",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-05-19T20:12:13Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7e212881840887b0f81c5373d4021103d16289f7",
          "body": "The CLI command layer was only 15% covered — no end-to-end test existed\nfor the credential-mutating commands, exactly where a regression silently\nloses user data. This adds a real regression gate.\n\ninternal/cli/command_test.go (new): 15 hermetic command tests. Each runs\na whole command via Root().Ex\n[…]\n bats\nis absent.\n\nflake.nix: devShells.default provides go + bats so `nix develop -c make\nconformance` works out of the box.\n\nVerified: make conformance green (vet + Go tests + 22 bats); nix build OK.",
          "is_bot": false,
          "headline": "test: build a hermetic conformance suite for the CLI layer",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-05-19T20:01:31Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8c14051d483f809f3032c475e85f5edcc59c401f",
          "body": "Resolves the three lower-severity security items left noted-but-unfixed\nafter the previous audit-fix pass.\n\n- L1: fetchZaiToken dropped its os.Stat + executable-bit precheck before\n  running ~/.claude/scripts/mcp-secret-cache.sh — that stat-then-exec was\n  a TOCTOU. A missing or non-executable helpe\n[…]\nd for\nCLI tools and not a defect\"; a hardcoded allowlist would break Nix/\nHomebrew installs for no real gain on a personal tool.\n\ngofmt/vet clean; Go unit tests + 15 bats smoke tests + nix build pass.",
          "is_bot": false,
          "headline": "fix(security): close out the remaining low-severity audit findings",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-05-19T19:42:46Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "51be7363ddf5f9bc7b1831b1ec1d9151ad45248f",
          "body": "Aggregated fixes from a code-quality review and a security audit of the\ngo-port branch.\n\nSECURITY\n\n- CRITICAL: setup-op-connect no longer shells out to `security\n  add-generic-password -w <secret>`, which exposed the 1Password Connect\n  bearer token and CF Access secrets in argv (visible to any loca\n[…]\n it queries sequentially; context flows from cmd.Context() in save /\n  env / remove-account instead of context.Background().\n\nAll gofmt/vet clean; Go unit tests + 15 bats smoke tests + nix build\npass.",
          "is_bot": false,
          "headline": "fix(security,quality): address audit findings on the Go port",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-05-19T19:17:52Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "fa104a54b88bd8a67253b4f6708a08e61e9dc1d0",
          "body": "credentials.Credentials is a typed inspection lens, not a faithful mirror\nof .credentials.json — json.Unmarshal into it drops any field the struct\ndoes not model. RefreshAll and usage-all's auto-refresh persisted\nnewCred.Marshal() output, so any field Claude Code adds to the credential\nfile in futur\n[…]\n blob with an\n  unmodeled field loses it across Parse->Marshal.\n- sync.TestSync_PreservesRawCredentialBytes proves a full sync pass\n  stores a credential blob (incl. an unmodeled field) byte-for-byte.",
          "is_bot": false,
          "headline": "fix(refresh): store raw credential bytes, never a re-marshaled struct",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-05-19T18:26:58Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "29dac2eac1f80326d981d87c4a52e331cfaf261f",
          "body": "… bash\n\nThe go-port branch had 15 of 23 subcommands. This finishes the port: all\ncommands are now native Go, the flake builds the Go binary, and ccswitch.sh\nis removed.\n\nNew subcommands\n  - login / refresh-all   wire up the existing internal/refresh package\n  - use-zai / use-anthropic / api-status  \n[…]\ntests/cli.bats: 15 end-to-end smoke tests in an isolated $HOME,\n    including regression coverage for the stale-active-account bug.\n\nRemoved\n  - ccswitch.sh (3269 lines) and tests/integration_test.sh.",
          "is_bot": false,
          "headline": "feat(go): complete the Go port — port remaining 8 subcommands, retire…",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-05-19T07:59:50Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "cada59ce39cd773c75b31b20a94f1e1146c79ec2",
          "body": "… daemon-panic\n\nNet: -71 lines. 14/14 sync tests pass (added one).\n\nData-loss bugs closed:\n- cli/push.go and cli/pull.go re-implemented sync logic against\n  hardcoded \"Claude Code Account - %s-%s\" keys (with spaces) while\n  sync.Engine uses account.BackupCredKey (\"Claude Code-Account-...\").\n  push/p\n[…]\ngo can persist after Pull\n  mutates the in-memory copy.\n\nTest:\n- TestSync_ActiveSlot_PullMirrorsBoth covers the new dual-write path\n  and would catch any regression in the order-sensitive writePulled.",
          "is_bot": false,
          "headline": "refactor(go): round-3 fixes from review — close data-loss, atomicity,…",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-04-26T14:42:43Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ac174d8953e5b722a9a7ca5dd256227a544de851",
          "body": "Net: -72 lines on top of the initial Go port. All 41 tests still pass.\n\nBig-impact:\n- Wire cli/sync.go and cli/daemon.go through sync.Engine/sync.Daemon.\n  Deletes ~120 lines of duplicate sync logic that was diverging in\n  key format (\"ccswitch - %s-%s\" vs \"Claude Code Account - %s-%s\").\n  Daemon is\n[…]\ns) + http.Client.Timeout=30s for the 5-min daemon\n- vault: drop kvPath identity wrapper\n- Demote per-account \"pushed/pulled\" log lines from Info to Debug\n  so a 5-min daemon at idle doesn't flood logs",
          "is_bot": false,
          "headline": "refactor(go): consolidate sync engine, centralize keys, polish",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-04-26T14:03:51Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b406e49553d9eb3575d05820ba2408aee5a79b05",
          "body": "Initial Go rewrite of ccswitch — feature-equivalent for read paths,\nbacked by a clean package layout for parallel hand-off.\n\nWhat's in:\n- cmd/ccswitch     — main, cobra root, all 16 subcommands\n- internal/account — sequence.json (v2 hash IDs), Resolve, atomic save\n- internal/backend — Backend interf\n[…]\n`list` reads \"Unknown\" because the bash sequence.json\n  uses \"Personal\" — minor format reconciliation\n- Wire ccswitch-daemon.nix to the Go binary\n- Replace ccswitch.sh on main once verified end-to-end",
          "is_bot": false,
          "headline": "feat(go): initial Go port (parallel agent team build)",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-04-26T05:10:05Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a0f7ee4534f908f1d8632f384d7df87085826ae9",
          "body": "Move bearer + CF Access headers to a curl config file fed via process\nsubstitution (`-K <(...)`), and pass JSON request bodies on stdin\n(`--data-binary @-`) instead of `--data \"$body\"`. Result: neither the\n1Password Connect bearer, the CF Access service-token client-secret,\nnor credential JSON appea\n[…]\nd for the HTTP path.\n\nDocument the residual `security add-generic-password -w VALUE` argv\nexposure (Apple offers no scriptable stdin alternative on macOS) in\ndocs/SECURITY.md. Tests: 13/13 still pass.",
          "is_bot": false,
          "headline": "security: keep Connect secrets out of curl argv",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-04-26T00:22:04Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ace44181820cf23c986604e5a4058b4ff9305770",
          "body": "`<<<\"$title\"` appends a newline; @uri encodes it as %0A and bakes it\ninto the filter expression, making every find_item_id miss. `printf %s`\navoids the extra byte.",
          "is_bot": false,
          "headline": "fix: strip trailing newline before jq @uri in find_item_id",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-04-25T22:52:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3a298985d6e76136ba61b9bb8fc4f59671603848",
          "body": "Net: +101 / -117 lines (smaller than the previous round). 13/13 tests pass.\n\nCode reuse:\n- Two new credential helpers replace 5+ inline python heredocs:\n  - _cred_field <json> <key> — extract a string from .claudeAiOauth via\n    jq (already a hard dep, no python fork)\n  - _cred_hours_left <ms> — pri\n[…]\nnger\n  re-resolves item_id after _op_read already cached it).\n- Removed python forks from _refresh_via_claude_auth and 4 hours-left\n  computations on hot paths (~30 ms × N accounts × every push/pull).",
          "is_bot": false,
          "headline": "refactor: round-2 simplification from review feedback",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-04-25T22:41:47Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "95ac8a871a0bbaacf4b6daa26fdf54e94681b8e0",
          "body": "Net: +84 / -97 lines (smaller, less duplication, no behavior change).\n13/13 integration tests still pass.\n\nCode reuse:\n- Replace 4× duplicated `op_args` read-loop with `mapfile -t _op_argv`\n  (bash 4+ already required) and a shared global. _op_read, _op_write,\n  _op_delete, _op_check now share one l\n[…]\nficiency:\n- One mapfile vs while-read loop per call (smaller fork count for\n  signed-in mode hot path).\n- Vault filter URL encoding no longer forks python per request (was\n  ~30ms × N items per sync).",
          "is_bot": false,
          "headline": "refactor: simplify ccswitch internals from review feedback",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-04-25T22:18:00Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4c0469133d43c82ad050f168b34a057126fbec8d",
          "body": "Connect endpoints behind Cloudflare Access can't be used via the op CLI —\nCF Access strips Authorization: Bearer headers, so the Connect server\nnever sees the token. Replace the op-CLI path with direct HTTP calls\nthat carry three headers (X-OP-Token, CF-Access-Client-Id,\nCF-Access-Client-Secret), wh\n[…]\np-CLI path is preserved as the fallback when\nOP_CONNECT_HOST is unset.\n\nTested: 13/13 integration tests pass (signed-in path). End-to-end HTTP\nConnect validation is interactive / environment-specific.",
          "is_bot": false,
          "headline": "feat: HTTP Connect backend with Cloudflare Access support",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-04-22T01:14:49Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "97e2cc790b8396edca8d3afa051ebafe09546aec",
          "body": "Integration tests (tests/integration_test.sh) exercise round-trip read/write\nfor each backend (file, keychain, 1password) plus config loading and\nbackend resolution. Three real bugs surfaced:\n\n1. _op_fill_args used `local -n` (bash 4.3+ nameref) — rejected by older\n   bash. Replaced with a portable \n[…]\n\nPlus a cosmetic: _keychain_delete leaked the deleted item's attribute\ndump to stdout — now `&>/dev/null` to silence both streams.\n\nRun: `bash tests/integration_test.sh`. Results: 13 passed, 0 failed.",
          "is_bot": false,
          "headline": "fix: bugs caught by new integration tests",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-04-22T00:37:29Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1cf5088fe1525b414d2fa2f3272791f44b1523cf",
          "body": "- New config: [backend.onepassword].connect_host + token_keychain_service\n  (env: OP_CONNECT_HOST, CCSWITCH_OP_CONNECT_TOKEN_KEYCHAIN_SERVICE)\n- _op_* functions drop --account flag when in Connect mode\n  (Connect tokens are already scoped to a server/vault)\n- _op_check probes via `op vault list` (wo\n[…]\nfrequent op/TouchID permission prompts caused by the sync daemon\nhammering whoami every 5 min. Connect tokens never expire (until revoked),\nso the daemon runs silently after one-time setup per device.",
          "is_bot": false,
          "headline": "feat: 1Password Connect support — no biometric prompts",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-04-20T19:17:43Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "6624d15860f3d4b7b5aad8a3af0f8c68d174cb9f",
          "body": null,
          "is_bot": false,
          "headline": "fix: _op_check honors CCSWITCH_OP_ACCOUNT for multi-account 1Password",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-04-19T05:46:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "66915e4b18b52b821868a4a74fe4648a81976d32",
          "body": "Add declarative configuration with precedence:\n  env vars > TOML config > built-in defaults\n\nSchema:\n  [backend]          type = auto|keychain|file|1password|vault\n  [backend.onepassword]   vault, item_prefix, account\n  [backend.vault]         addr, path, token\n  [sync]             interval\n  [refre\n[…]\n config key: passes --account to op CLI\n  (supports multi-account 1Password setups)\n- CCSWITCH_CONFIG_FILE env var to override config path\n- All op item get/edit/create/delete commands honor --account",
          "is_bot": false,
          "headline": "feat: TOML config file at ~/.config/ccswitch/config.toml",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-04-19T05:36:58Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a4609f3905c0789dd66fd31b97820a70b5e53c57",
          "body": "Add four new commands for syncing ccswitch state with 1Password:\n\n  --push            Upload all local credentials + sequence metadata\n  --pull            Download all credentials + sequence metadata (overwrites local)\n  --sync [--quiet]  Bi-directional merge; per-account newest expiresAt wins,\n    \n[…]\nSWITCH_OP_VAULT}, prefix ${CCSWITCH_OP_ITEM_PREFIX}.\n\nThe active account's live keychain entry is updated when remote is fresher\nso running Claude sessions inherit refreshed tokens on next auth check.",
          "is_bot": false,
          "headline": "feat: 1Password sync — push, pull, bi-directional sync, and daemon",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-04-19T04:37:34Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "bae0a2636e2cffd6e330b06fc11dfd922c7832ed",
          "body": "…ve keychain\n\nRefresh no longer temporarily swaps credentials into the active keychain\nslot, which could disrupt a running Claude session. Instead, creates an\nisolated CLAUDE_CONFIG_DIR with .credentials.json, runs `claude auth login`\nthere, and reads the refreshed creds from the file. The active session's\nkeychain entry is never touched during refresh.",
          "is_bot": false,
          "headline": "fix: refresh uses isolated CLAUDE_CONFIG_DIR instead of swapping acti…",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-04-10T14:00:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "de55b3068b7de1c81f3a1e7bec8eea9b89284f07",
          "body": "Remove direct calls to the OAuth token endpoint (console.anthropic.com).\nPer Anthropic guidance:\n- Direct refresh calls can invalidate Claude Code's active token\n- Refresh tokens are single-use; concurrent refreshes race\n- The supported path is `claude auth login` with env vars\n\nNew flow uses CLAUDE\n[…]\nerations run in a temp working directory to avoid\npolluting sessions.\n\nFor inactive accounts, temporarily swaps credentials into the active\nkeychain slot, runs the refresh, then restores the original.",
          "is_bot": false,
          "headline": "refactor: use claude auth login for refresh instead of direct OAuth API",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-04-10T13:48:36Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1d85d70024e67172d1c8f58c053fa23241dc713c",
          "body": null,
          "is_bot": false,
          "headline": "fix: --login runs claude in temp dir to avoid polluting project sessions",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-04-10T13:26:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "47a2293b42c1278eaee6ab6d35d0dd5aaaf806d7",
          "body": "Previous approach used CLAUDE_CONFIG_DIR with temp dirs, but on macOS\nClaude Code writes credentials to Keychain (not .credentials.json),\nusing a hashed service name tied to the config dir path. This meant\ncredentials from interactive login were never captured.\n\nNew approach:\n1. Switch to each expir\n[…]\nt_credentials\n5. Restore the original account when done\n\nThis works because Claude Code's auth flow always writes to the standard\n\"Claude Code-credentials\" Keychain entry when it's the active session.",
          "is_bot": false,
          "headline": "fix: --login now uses real account switching + native keychain auth",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-04-09T12:32:49Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5222882eb3e5e5ca53cca98a4d28e1fae5069d92",
          "body": "ccswitch --login finds accounts with expired/invalid credentials and\nlaunches `claude /login` in an isolated CLAUDE_CONFIG_DIR for each one,\nprompting the user to log in via browser. After claude exits, the fresh\ncredentials are captured and saved to the backup slot.\n\nOptions:\n  --only <hash|email> \n[…]\nR with expected identity\n3. Launch `claude /login` interactively\n4. Capture fresh credentials on exit\n5. Save to backup slot with the expected hash ID\n6. Warn if logged-in email doesn't match expected",
          "is_bot": false,
          "headline": "feat: add --login for interactive re-auth of expired accounts",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-04-09T02:04:28Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "57397718969b76667dbc6fa3ac02d7f681733c22",
          "body": "- Add _refresh_via_claude helper that runs `claude -p` with CLAUDE_CONFIG_DIR\n  pointing at a temp directory with the account's credentials. Claude Code's\n  internal auth flow handles refresh (including rate limits, one-time tokens).\n- refresh_account_token tries claude CLI first, falls back to dire\n[…]\ntaleness\n  scenario (backup slots going stale while active token gets refreshed).\n- Clearer error messages when refresh fails due to invalidated refresh token\n  (suggests re-auth via switch + claude).",
          "is_bot": false,
          "headline": "feat: use claude CLI for token refresh instead of direct OAuth API",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-04-09T01:44:17Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f769f5ce1730e476a302885aa27333739504f462",
          "body": "Account IDs are now deterministic 8-char SHA-256 hex prefix of the email\n(e.g., 86523df2 for zctaylor.work@gmail.com). This makes account identity\nstable and identifiable.\n\nChanges:\n- sequence.json v2 schema: accounts keyed by hash, activeAccountId\n- Auto-migration from v1 (numeric) to v2 on first r\n[…]\nash IDs\n- JSON output uses \"id\" field instead of \"account\" (number)\n\nBackward compatible: numeric index still works as positional lookup\ninto the sequence array (e.g., --switch-to 2 = second account).",
          "is_bot": false,
          "headline": "refactor: migrate from numeric account keys to email-hash IDs",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-04-06T14:57:32Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "55fa3f5d0c46560b571db43965260b60d6afbf1f",
          "body": "After logging in or re-authenticating via Claude Code, run:\n  ccswitch --save\n\nThis copies the active keychain credentials to the backup slot,\nensuring the backup has the fresh token. Prevents stale tokens\nin backup slots after Claude Code refreshes during a session.\n\nAlso detects identity mismatch (e.g., logged into a different\naccount than expected) and updates the account mapping.",
          "is_bot": false,
          "headline": "feat: add --save to capture fresh credentials after login",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-04-06T13:30:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c8a8f8b14b50b180ac452fc7b72b4afeb7058fd6",
          "body": "- Add _token_is_expired, _refresh_token, refresh_account_token helpers\n- Auto-refresh in --usage-all before querying the API\n- Auto-refresh in perform_switch before activating target account\n- Add --refresh-all command to manually refresh all expired tokens\n- 2s delay between refreshes to avoid rate limits",
          "is_bot": false,
          "headline": "feat: automatic OAuth token refresh for expired accounts",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-04-06T13:05:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "88917a5b13e814bf1559bc8dbe473426e7f47f54",
          "body": "Supports container/CI workflows where credentials are mounted:\n  eval \"$(ccswitch --env --creds-file /mnt/secrets/creds.json)\"\n  eval \"$(ccswitch --env --creds-file /s/creds.json --config-dir /tmp/ci)\"\n\nCredentials file is symlinked (not copied) so mounted volumes stay live.\nConfig dir gets symlinks to shared settings/hooks/skills/agents/MCP/plugins.",
          "is_bot": false,
          "headline": "feat: add --creds-file and --config-dir to --env for mounted secrets",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-04-06T01:46:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6ab0152c21af1a14b118fcf05ca1f9b9c5bc7b66",
          "body": "Add support for multiple credential storage backends:\n- keychain: macOS Keychain (default on macOS)\n- file: filesystem credentials (default on Linux/WSL)\n- 1password: 1Password CLI (op) with configurable vault\n- vault: HashiCorp Vault / OpenBao KV secrets engine\n\nBackend selection via CCSWITCH_BACKE\n[…]\neychain users are unaffected (auto default).\n\nConfig env vars:\n  CCSWITCH_OP_VAULT, CCSWITCH_OP_ITEM_PREFIX (1Password)\n  CCSWITCH_VAULT_ADDR, CCSWITCH_VAULT_PATH, CCSWITCH_VAULT_TOKEN (Vault/OpenBao)",
          "is_bot": false,
          "headline": "feat: pluggable credential backends (1Password, Vault/OpenBao)",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-04-05T21:18:28Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "66e5faee0f75aff40410d52da9956254bdf3023f",
          "body": null,
          "is_bot": false,
          "headline": "feat: add --json flag to --usage-all for machine-readable output",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-04-05T19:20:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c269c6287534f6eb98e26c5d5f8858fcdcfd4442",
          "body": "eval \"$(ccswitch --env 2)\" binds the current shell to account 2\nvia CLAUDE_CONFIG_DIR without affecting the global account.\n\nCreates ~/.claude-env-<N>/ with symlinks to shared config\n(settings, hooks, skills, agents, MCP, plugins) and isolated\ncredentials + projects directory per account.\n\neval \"$(ccswitch --env --unset)\" reverts to global.",
          "is_bot": false,
          "headline": "feat: add --env for per-shell account binding",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-04-05T19:01:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fb1ed87a56ecec98544e6498519614789c6ba907",
          "body": null,
          "is_bot": false,
          "headline": "fix: add dontBuild to prevent Makefile from running in nix build",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-04-05T18:24:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5f37f014f33f3f5d2fa492745e83759e2f4c60f0",
          "body": "Multi-account switcher and usage monitor for Claude Code.\nSupports nix flake, homebrew, and manual install.",
          "is_bot": false,
          "headline": "feat: initial release of ccswitch v1.0.0",
          "author_name": "Zach Taylor",
          "author_login": "zach-source",
          "committed_at": "2026-04-05T18:20:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 1,
      "commits_last_year": 60,
      "latest_release_at": "2026-07-26T18:34:30Z",
      "latest_release_tag": "v2.8.0",
      "releases_from_tags": false,
      "days_since_last_push": 3,
      "active_weeks_last_year": 10,
      "days_since_latest_release": 3,
      "mean_days_between_releases": null
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": false,
      "health_percentage": 57,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "github.com/zach-source/ccswitch",
          "exists": true,
          "license": null,
          "keywords": [],
          "ecosystem": "go",
          "matches_repo": true,
          "registry_url": "https://pkg.go.dev/github.com/zach-source/ccswitch",
          "is_deprecated": false,
          "latest_version": "v1.6.0",
          "repository_url": "https://github.com/zach-source/ccswitch",
          "versions_count": 17,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": null,
          "latest_published_at": "2026-04-06T13:30:37Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 114
        }
      ]
    },
    "popularity": {
      "forks": 0,
      "stars": 1,
      "watchers": 0,
      "fork_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_forks": 0
      },
      "star_history": null,
      "open_issues_and_prs": 1
    },
    "ai_readiness": {
      "has_nix": true,
      "example_dirs": [],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": false,
      "bootstrap_files": [
        "Makefile"
      ],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [],
      "toolchain_manifests": [
        "go.mod"
      ],
      "largest_source_bytes": 18504,
      "source_files_sampled": 67,
      "oversized_source_files": 0,
      "agent_instruction_files": [],
      "agent_instruction_max_bytes": null
    },
    "dependencies": {
      "manifests": [
        "go.mod"
      ],
      "advisories": {
        "error": null,
        "scope": null,
        "source": null,
        "findings": [],
        "collected": false,
        "malicious": [],
        "truncated": false,
        "by_severity": {},
        "advisory_count": 0,
        "affected_count": 0,
        "assessed_count": 0,
        "malicious_count": 0,
        "assessed_package": null,
        "unassessed_count": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "go"
      ],
      "dependencies": [
        {
          "name": "github.com/hashicorp/vault/api",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.23.0"
        },
        {
          "name": "github.com/keybase/go-keychain",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.0.1"
        },
        {
          "name": "github.com/pelletier/go-toml/v2",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v2.3.0"
        },
        {
          "name": "github.com/spf13/cobra",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.10.2"
        },
        {
          "name": "golang.org/x/term",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.42.0"
        }
      ],
      "all_dependencies": {
        "error": "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
        "source": null,
        "packages": [],
        "collected": false,
        "truncated": false,
        "total_count": null,
        "direct_count": null,
        "indirect_count": null
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 0,
        "merged_prs": 13,
        "open_issues": 1,
        "closed_ratio": 0,
        "closed_issues": 0,
        "closed_unmerged_prs": 1
      },
      "bus_factor": 1,
      "bot_contributors": 0,
      "top_contributors": [
        {
          "type": "User",
          "login": "zach-source",
          "commits": 60,
          "avatar_url": "https://avatars.githubusercontent.com/u/61884887?v=4"
        }
      ],
      "contributors_sampled": 1,
      "top_contributor_share": 1
    },
    "quality_signals": {
      "has_ci": false,
      "has_tests": true,
      "ci_workflows": [],
      "has_docs_dir": true,
      "linter_configs": [],
      "has_editorconfig": false,
      "has_linter_config": false,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [
        "go.sum"
      ],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": 0,
            "reason": "branch protection not enabled on development/release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": 0,
            "reason": "0 out of 13 merged PRs checked by a CI test -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 0,
            "reason": "Found 0/16 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 3,
            "reason": "project has 1 contributing companies or organizations -- score normalized to 3",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": null,
            "reason": "no workflows found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 0,
            "reason": "no update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 10,
            "reason": "license file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 10,
            "reason": "30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": null,
            "reason": "packaging workflow not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": null,
            "reason": "no dependencies found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "SAST tool is not run on all commits -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 4,
            "reason": "security policy file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": null,
            "reason": "no releases found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": null,
            "reason": "No tokens found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 0,
            "reason": "25 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "4406b5ab832cd4c29b6e1a655cd2269a3ce13a80",
        "ran_at": "2026-07-29T21:23:22Z",
        "aggregate_score": 2.9,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": true,
      "has_dependabot_config": false
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": null,
      "oldest_open_prs": [],
      "last_merged_pr_at": "2026-07-26T18:29:58Z",
      "ci_last_conclusion": null,
      "oldest_open_issues": [
        {
          "number": 14,
          "created_at": "2026-07-18T04:04:07Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ]
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/zach-source/ccswitch",
    "host": "github.com",
    "name": "ccswitch",
    "owner": "zach-source"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "at_risk",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 45,
      "inputs": {
        "security": 29,
        "vitality": 75,
        "community": 24,
        "governance": 46,
        "engineering": 44
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "good",
        "name": "Vitality",
        "value": 75,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "moderate",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 69,
            "inputs": {
              "commits_last_year": 60,
              "human_commit_share": 1,
              "days_since_last_push": 3,
              "active_weeks_last_year": 10
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 3 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 3
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "10/52 weeks with commits",
                "points": 6.9,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 10
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "60 commits in the last year",
                "points": 16,
                "status": "partial",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 60
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "good",
            "name": "Release discipline",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 84,
            "inputs": {
              "releases_count": 1,
              "latest_release_tag": "v2.8.0",
              "releases_from_tags": false,
              "days_since_latest_release": 3,
              "mean_days_between_releases": null
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "1 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 3 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 3
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "cadence unknown (single release)",
                "points": 12.6,
                "status": "partial",
                "details": [
                  {
                    "code": "release_cadence_unknown",
                    "params": {}
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "excellent",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "unverified",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": "repository_too_young",
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": null,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "maintenance record not established from the collected data",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_unverified",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "critical",
        "name": "Community & Adoption",
        "value": 24,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 1,
            "inputs": {
              "forks": 0,
              "stars": 1,
              "watchers": 0,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "1 stars",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "0 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "0 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "moderate",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 50,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "has_contributing": false,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "has_pull_request_template": false
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "recognized license (MIT)",
                "points": 22.5,
                "status": "met",
                "details": [
                  {
                    "code": "license_standard",
                    "params": {}
                  },
                  {
                    "code": "license_spdx",
                    "params": {
                      "spdx": "MIT"
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "code_of_conduct",
                "name": "Code of conduct",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 13.5
              },
              {
                "key": "issue_template",
                "name": "Issue template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.2
              },
              {
                "key": "pr_template",
                "name": "PR template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.3
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "at_risk",
        "name": "Sustainability & Governance",
        "value": 46,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 13,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 1,
              "top_contributor_share": 1
            },
            "components": [
              {
                "key": "bus_factor",
                "name": "Bus factor",
                "detail": "1 contributor(s) cover half of all commits",
                "points": 9,
                "status": "partial",
                "details": [
                  {
                    "code": "bus_factor",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 54
              },
              {
                "key": "commit_distribution",
                "name": "Commit distribution",
                "detail": "top contributor authored 100% of commits",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "1 contributors",
                "points": 1.4,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 1 contributing companies or organizations -- score normalized to 3",
                "points": 3,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "at_risk",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 36,
            "inputs": {
              "merged_prs": 13,
              "open_issues": 1,
              "closed_issues": 0,
              "issue_closed_ratio": 0,
              "closed_unmerged_prs": 1
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "0% of issues closed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 0
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "13/14 decided PRs merged",
                "points": 35.5,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 13,
                      "decided": 14
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/16 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "moderate",
            "name": "Ownership & stewardship",
            "note": "Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "verified_domain"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 54,
            "inputs": {
              "followers": 12,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "zach-source",
              "public_repos": 90,
              "account_age_days": 2336
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "personal (user) account",
                "points": 10,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_personal",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": "not applicable to user accounts",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "not_applicable_to_user_accounts",
                    "params": {}
                  }
                ],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "12 followers of zach-source",
                "points": 8,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 12,
                      "login": "zach-source"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "90 public repos, account ~6 yr old",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 90
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 6
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "github.com/zach-source/ccswitch"
              ],
              "ecosystems": "go",
              "any_deprecated": false,
              "min_days_since_publish": 114
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "1 package(s) on go",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 1,
                      "ecosystems": "go"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "publish_recency",
                "name": "Publish recency",
                "detail": "latest publish 114 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 114
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "17 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 17
                    }
                  }
                ],
                "max_points": 20
              },
              {
                "key": "not_deprecated",
                "name": "Not deprecated",
                "detail": "active, not deprecated or yanked",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "package_not_deprecated",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
      },
      {
        "key": "engineering",
        "band": "at_risk",
        "name": "Engineering Quality",
        "value": 44,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "critical",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 24,
            "inputs": {
              "has_ci": false,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 24
              },
              {
                "key": "tests_present",
                "name": "Tests present",
                "detail": null,
                "points": 24,
                "status": "met",
                "details": [],
                "max_points": 24
              },
              {
                "key": "linter_config",
                "name": "Linter config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 16
              },
              {
                "key": "pre_commit_hooks",
                "name": "Pre-commit hooks",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 9.6
              },
              {
                "key": "editorconfig",
                "name": ".editorconfig",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.4
              },
              {
                "key": "openssf_scorecard_ci_tests",
                "name": "OpenSSF Scorecard: CI-Tests",
                "detail": "0 out of 13 merged PRs checked by a CI test -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "good",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 75,
            "inputs": {
              "topics": [],
              "has_wiki": true,
              "homepage": null,
              "has_readme": true,
              "has_docs_dir": true,
              "has_description": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 30,
                "status": "met",
                "details": [],
                "max_points": 30
              },
              {
                "key": "documentation_directory",
                "name": "Documentation directory",
                "detail": null,
                "points": 25,
                "status": "met",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "critical",
        "name": "Security",
        "value": 29,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "critical",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Dangerous-Workflow, Packaging, Pinned-Dependencies, Signed-Releases, Token-Permissions. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "dangerous_workflow",
                    "packaging",
                    "pinned_dependencies",
                    "signed_releases",
                    "token_permissions"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 29,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 13,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 5,
              "scorecard_aggregate": 2.9
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "branch protection not enabled on development/release branches",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "0 out of 13 merged PRs checked by a CI test -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "Found 0/16 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 1 contributing companies or organizations -- score normalized to 3",
                "points": 0.8,
                "status": "partial",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no workflows found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "no update tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file detected",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow not detected",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "no dependencies found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "SAST tool is not run on all commits -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file detected",
                "points": 2,
                "status": "partial",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "No tokens found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "25 existing vulnerabilities detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              }
            ]
          }
        ],
        "description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
      },
      {
        "key": "ai_readiness",
        "band": "moderate",
        "name": "AI Readiness",
        "value": 64,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "at_risk",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 1,
              "agent_instruction_files": [],
              "agent_instruction_max_bytes": null
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "no CLAUDE.md / AGENTS.md / editor rules",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_agent_instructions",
                    "params": {}
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "60 of 60 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 60,
                      "sampled": 60
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "moderate",
            "name": "Verify loop (build / test / typecheck)",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Pinned-Dependencies. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_pinned_dependencies"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 68,
            "inputs": {
              "has_nix": true,
              "has_tests": true,
              "lockfiles": [
                "go.sum"
              ],
              "has_dockerfile": false,
              "typed_language": true,
              "bootstrap_files": [
                "Makefile"
              ],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [],
              "agent_commit_share": 0,
              "toolchain_manifests": [
                "go.mod"
              ],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": "Makefile",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "Makefile"
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "automated_tests",
                "name": "Automated tests",
                "detail": null,
                "points": 22,
                "status": "met",
                "details": [],
                "max_points": 22
              },
              {
                "key": "lint_format_config",
                "name": "Lint / format config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "Go (statically typed)",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "Go"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": "Nix, lockfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "Nix, lockfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "no agent-authored commits among the last 60",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_agent_authored_commits",
                    "params": {
                      "sampled": 60
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "no automated dependency updates observed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_dependency_automation",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "no dependencies found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "primary_language": "Go",
              "largest_source_bytes": 18504,
              "source_files_sampled": 67,
              "oversized_source_files": 0
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "Go (statically typed)",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "Go"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "0/67 source files over 60KB",
                "points": 55,
                "status": "met",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 67,
                      "oversized": 0
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
      }
    ],
    "metrics_version": "1.13.0"
  },
  "warnings": [
    "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
    "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-29T21:23:35.110544Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/z/zach-source/ccswitch.svg",
  "full_name": "zach-source/ccswitch",
  "license_state": "standard",
  "license_spdx": "MIT"
}

Scores are signals, not warranties. They reflect publicly visible practices on GitHub — not a code audit, and not a security guarantee.

Missing data is excluded and weights renormalized, never scored as zero. Methodology is versioned and open: metrics v1.13.0, schema v0.27.0 — full methodology · metrics wiki.

How one result sits in the wider record: aggregate statisticsGo.