Öffentliches Register
Software-GesundheitsberichtSchema 0.27.0 · Metriken 1.13.0 · 2026-07-29 21:23 UTC

zach-source / ccswitch

Multi-account switcher and usage monitor for Claude Code

GoMIT★ 1 Stern⑂ 0 Forksseit Apr. 2026Auf GitHub ansehen ↗

zach-source/ccswitch erreicht einen Gesundheitsindex von 45 von 100 und liegt damit im Bereich Gefährdet. Am stärksten schneidet es bei Vitality (75/100) ab, am schwächsten bei Community & Adoption (24/100). Zuletzt vor 3 Tagen aktualisiert. Ein einzelner Mitwirkender trägt den Großteil der jüngsten Arbeit.

45
gesamt / 100
Gefährdet

Software-Gesundheitsindex

Metriken werden auf einer Skala von 1–100 in gewichtete Kategorien gruppiert. Der Gesamtwert beginnt als ihr Mittel; sobald öffentliche Evidenz die Richtlinie für Hochrisikojurisdiktionen auslöst, wird die Bewertung angepasst und erhält die Obergrenze 49 (Gefährdet). AI Readiness liegt außerhalb.

45
Exzellent85-100Vorbildlich; erfüllt im Wesentlichen alle geprüften Kriterien
Gut70-84Gesund; geringfügige Lücken
Mittel50-69Akzeptabel mit deutlichen Lücken; Überprüfung empfohlen
Gefährdet30-49Erhebliche Schwächen; eine Übernahme erfordert Vorsicht
Kritisch1-29Schwerwiegende Probleme (aufgegeben, nur ein Maintainer, keine Hygiene)
VitalitätCommunity &VerbreitungNachhaltigkeit &GovernanceEngineering-QualitätSicherheitAI Readiness

Bewertungsprofil

Jede Achse ist eine Kategorie. Die Form zählt mehr als der Durchschnitt — ein gesundes Projekt füllt die gesamte Fläche, während ein Profil aus Spitzen und Kratern bedeutet, dass Stärke in einer Dimension Risiken in einer anderen verdeckt.

Eigentümerschaft

Zachary TaylorPersönliches Konto
12 Follower90 öffentliche Reposseit März 2020Ripple

Dieses Repository gehört einem persönlichen Konto. Ein Projekt mit nur einem Eigentümer trägt ein höheres Kontinuitätsrisiko als ein organisationsgetragenes.

Paket-Ökosysteme

RegistryPaketVersionDownloads / MonatVersionenZuletzt veröffentlicht
Gogithub.com/zach-source/ccswitchv1.6.0-17vor 114 Tagen

Metriken nach Kategorie

Vitalität

Lebt das Projekt — wird Code geschrieben und werden Releases ausgeliefert?

75Gut · 22 % des Gesamtindex
Wie die Bewertung erfolgt
36/36Push-Aktualität — letzter Push vor 3 Tagen
6.9/36Commit-Rhythmus — 10/52 Wochen mit Commits
16/18Commit-Volumen — 60 Commits im letzten Jahr
10/10OpenSSF Scorecard: Maintained — 30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10
Verwendete Eingangsdaten
commits_last_year60
human_commit_share1
days_since_last_push3
active_weeks_last_year10
Wie die Bewertung erfolgt
27/27Liefert Releases aus — 1 Releases veröffentlicht
36/36Release-Aktualität — letztes Release vor 3 Tagen
12.6/27Release-Rhythmus — Rhythmus unbekannt (nur ein Release)
0/10OpenSSF Scorecard: Signed-Releases — keine Daten
Verwendete Eingangsdaten
releases_count1
latest_release_tagv2.8.0
releases_from_tagsnein
days_since_latest_release3
mean_days_between_releases
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): OpenSSF Scorecard: Signed-Releases. Die verbleibenden Gewichte wurden renormalisiert.

Community & Verbreitung

Hat das Projekt Nutzer, Downloads, Aufmerksamkeit und ein einladendes Umfeld für Beitragende?

24Kritisch · 18 % des Gesamtindex
Wie die Bewertung erfolgt
0/60Stars — 1 Stars
0/25Forks — 0 Forks
0/15Watcher — 0 Watcher
Verwendete Eingangsdaten
forks0
stars1
watchers0
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Wie die Bewertung erfolgt
22.5/22.5README
22.5/22.5Lizenz — anerkannte Lizenz (MIT)
0/18CONTRIBUTING-Leitfaden
0/13.5Verhaltenskodex
0/7.2Issue-Vorlage
0/6.3PR-Vorlage
Verwendete Eingangsdaten
has_readmeja
has_licenseja
has_contributingnein
has_issue_templatenein
has_code_of_conductnein
has_pull_request_templatenein

Nachhaltigkeit & Governance

Überdauert das Projekt die Menschen, die es tragen — Bus-Faktor, Reaktionsfähigkeit, Trägerschaft und Paketpflege?

46Gefährdet · 24 % des Gesamtindex
Wie die Bewertung erfolgt
9/54Bus-Faktor — 1 Beitragende decken die Hälfte aller Commits ab
0/22.5Commit-Verteilung — wichtigste beitragende Person verfasste 100 % der Commits
1.4/13.5Breite der Beitragenden — 1 Beitragende
3/10OpenSSF Scorecard: Contributors — project has 1 contributing companies or organizations -- score normalized to 3
Verwendete Eingangsdaten
bus_factor1
contributors_sampled1
top_contributor_share1
Wie die Bewertung erfolgt
0/46.8Issue-Lösungsquote — 0 % der Issues geschlossen
35.5/38.3PR-Annahme — 13/14 entschiedene PRs gemergt
0/15OpenSSF Scorecard: Code-Review — Found 0/16 approved changesets -- score normalized to 0
Verwendete Eingangsdaten
merged_prs13
open_issues1
closed_issues0
issue_closed_ratio0
closed_unmerged_prs1
Wie die Bewertung erfolgt
10/30Organisatorische Trägerschaft — persönliches (Nutzer-)Konto
0/20Verifizierte Domain — für Nutzerkonten nicht anwendbar
8/25Reichweite des Inhabers — 12 Follower von zach-source
25/25Kontohistorie — 90 öffentliche Repos, Kontoalter ca. 6 Jahre
Verwendete Eingangsdaten
followers12
owner_typeUser
is_verified
owner_loginzach-source
public_repos90
account_age_days2.336
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): Verifizierte Domain. Die verbleibenden Gewichte wurden renormalisiert.

Paketpflege

100Exzellent
Wie die Bewertung erfolgt
25/25Veröffentlicht & auflösbar — 1 Paket(e) auf go
35/35Veröffentlichungsaktualität — letzte Veröffentlichung vor 114 Tagen
20/20Versionshistorie — 17 veröffentlichte Versionen
20/20Nicht veraltet — aktiv, nicht veraltet oder zurückgezogen
Verwendete Eingangsdaten
packagesgithub.com/zach-source/ccswitch
ecosystemsgo
any_deprecatednein
min_days_since_publish114

Engineering-Qualität

Sind grundlegende Engineering- und Dokumentationspraktiken vorhanden?

44Gefährdet · 20 % des Gesamtindex
Wie die Bewertung erfolgt
0/24CI-Workflows
24/24Tests vorhanden
0/16Linter-Konfiguration
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
Verwendete Eingangsdaten
has_cinein
has_testsja
has_editorconfignein
has_linter_confignein
has_precommit_confignein
Wie die Bewertung erfolgt
30/30README
25/25Dokumentationsverzeichnis
0/15Dokumentations-/Homepage-Site
10/10Repository-Beschreibung
0/10Topics
10/10Wiki
Verwendete Eingangsdaten
topics
has_wikija
homepage
has_readmeja
has_docs_dirja
has_descriptionja

Sicherheit

Sind die sichtbaren Sicherheits- und Lieferkettenpraktiken belastbar, ohne ungeklärte Exposition gegenüber Hochrisikojurisdiktionen?

29Kritisch · 16 % des Gesamtindex

Sicherheitslage

29Kritisch
Wie die Bewertung erfolgt
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 — keine Daten
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5Lizenz — 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 — keine Daten
0/5Pinned-Dependencies — keine Daten
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 — keine Daten
0/7.5Token-Permissions — keine Daten
0/7.5Vulnerabilities — 25 existing vulnerabilities detected
Verwendete Eingangsdaten
sourceopenssf_scorecard
checks_evaluated13
scorecard_versionv5.5.0
checks_inconclusive5
scorecard_aggregate2,9
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): dangerous_workflow, packaging, pinned_dependencies, signed_releases, token_permissions. Die verbleibenden Gewichte wurden renormalisiert.

AI Readiness

Wie gut ist das Repository dafür ausgestattet, mit KI-Coding-Agenten entwickelt und gepflegt zu werden? Ein unabhängiges, experimentelles Badge — Gewicht 0,0, es wird eigenständig ausgewiesen und verändert den Gesamt-Gesundheitswert nicht.

64Mittel · 0 % des Gesamtindex
Wie die Bewertung erfolgt
0/45Agentenanweisungen — keine CLAUDE.md / AGENTS.md / Editor-Regeln
0/15Maschinenlesbare Doku (llms.txt)
40/40Lesbare Commit-Historie — 60 von 60 menschlichen Commits benennen ihre Absicht (strukturierter Betreff oder erläuternder Text)
Verwendete Eingangsdaten
has_llms_txtnein
legible_history_share1
agent_instruction_files
agent_instruction_max_bytes
Wie die Bewertung erfolgt
18/18Bootstrap mit einem Befehl — Makefile
22/22Automatisierte Tests
0/11Lint-/Format-Konfiguration
11/11Statische Typprüfung — Go (statisch typisiert)
10/10Reproduzierbare Umgebung — Nix, lockfile
0/10Belegte Agentenpraxis — keine von Agenten verfassten Commits unter den letzten 60
0/8Automatisierte Wartung — keine automatisierten Abhängigkeits-Updates beobachtet
0/10OpenSSF Scorecard: Pinned-Dependencies — keine Daten
Verwendete Eingangsdaten
has_nixja
has_testsja
lockfilesgo.sum
has_dockerfilenein
typed_languageja
bootstrap_filesMakefile
has_devcontainernein
has_linter_confignein
typecheck_configs
agent_commit_share0
toolchain_manifestsgo.mod
dependency_bot_commit_share0
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): OpenSSF Scorecard: Pinned-Dependencies. Die verbleibenden Gewichte wurden renormalisiert.
Wie die Bewertung erfolgt
45/45Typprüfbarer Code — Go (statisch typisiert)
55/55Handhabbare Dateigrößen — 0/67 Quelldateien über 60 KB
Verwendete Eingangsdaten
primary_languageGo
largest_source_bytes18.504
source_files_sampled67
oversized_source_files0

Eckdaten

1GitHub-Sterne
1Mitwirkende
60Commits, letzte 12 Monate
3Tage seit letztem Push
1Releases
1Bus-Faktor
1offene Issues
GoPaket-Ökosysteme

Warnungen zur Datenerhebung

  • 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

Weitere Details

OpenSSF Scorecard 2.9 / 10
2.9Gesamtwert

Unabhängige, werkzeugneutrale Sicherheitsbewertung durch das quelloffene OpenSSF Scorecard. Jede Prüfung honoriert eine Sicherheits-Praxis, nicht das Werkzeug eines bestimmten Anbieters. Prüfungen, die Scorecard nicht ermitteln konnte, sind mit k. A. markiert und vom Sicherheitswert ausgeschlossen (nie als null gezählt).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
k. A.Dangerous-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
k. A.Packagingpackaging workflow not detected
k. A.Pinned-Dependenciesno dependencies found
0SASTSAST tool is not run on all commits -- score normalized to 0
4Security-Policysecurity policy file detected
k. A.Signed-Releasesno releases found
k. A.Token-PermissionsNo tokens found
0Vulnerabilities25 existing vulnerabilities detected
Direkte Abhängigkeiten 5
RegistryPaketVersionsvorgabeManifest
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
Alle Abhängigkeiten nicht erhoben

Der aufgelöste Abhängigkeitssatz konnte für diesen Bericht nicht erhoben werden: GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

JSON-Rohbericht maschinenlesbar
{
  "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"
}

Bewertungen sind Signale, keine Garantien. Sie spiegeln öffentlich sichtbare Praxis auf GitHub wider — kein Code-Audit und keine Sicherheitsgarantie.

Fehlende Daten werden ausgeschlossen und die Gewichte neu normiert, nie als null bewertet. Die Methodik ist versioniert und offen: Metriken v1.13.0, Schema v0.27.0 — vollständige Methodik · Metriken-Wiki.

Wie ein einzelnes Ergebnis im Gesamtregister steht: aggregierte StatistikenGo.