Registro público
Informe de salud del softwareesquema 0.27.0 · métricas 1.13.0 · 2026-07-29 21:23 UTC

zach-source / ccswitch

Multi-account switcher and usage monitor for Claude Code

GoMIT★ 1 estrella⑂ 0 forksdesde abr 2026Ver en GitHub ↗

zach-source/ccswitch tiene un índice de salud de 45 sobre 100, lo que lo sitúa en la banda En riesgo. Su puntuación más alta es Vitality (75/100) y la más baja, Community & Adoption (24/100). Se actualizó por última vez hace 3 días. Una sola persona concentra la mayor parte del trabajo reciente.

45
global / 100
En riesgo

Índice de salud del software

Las métricas se agrupan en categorías ponderadas sobre una escala de 1 a 100. El resultado global parte de su media; cuando la evidencia pública activa la Política de Jurisdicciones de Alto Riesgo, la calificación se ajusta y recibe el límite 49 (En riesgo). Preparación para IA queda fuera.

45
Excelente85-100Ejemplar; cumple prácticamente todos los criterios evaluados
Bueno70-84Saludable; carencias menores
Moderado50-69Aceptable con carencias notables; se recomienda revisión
En riesgo30-49Debilidades significativas; su adopción exige cautela
Crítico1-29Problemas graves (proyecto abandonado, un solo mantenedor, sin higiene)
VitalidadComunidad yAdopciónSostenibilidady GobernanzaCalidad deIngenieríaSeguridadPreparaciónpara IA

Perfil de puntuación

Cada eje es una categoría. La forma importa más que la media: un proyecto sano llena toda la figura, mientras que un perfil de picos y cráteres indica que la fortaleza en una dimensión enmascara el riesgo en otra.

Titularidad

Zachary TaylorCuenta personal
12 seguidores90 repositorios públicosdesde mar 2020Ripple

Este repositorio pertenece a una cuenta personal. Un proyecto con un único propietario conlleva más riesgo de continuidad que uno respaldado por una organización.

Ecosistemas de paquetes

RegistroPaqueteVersiónDescargas / mesVersionesÚltima publicación
Gogithub.com/zach-source/ccswitchv1.6.0-17hace 114 días

Métricas por categoría

Vitalidad

¿Está vivo el proyecto: se escribe código y se publican versiones?

75Bueno · 22% del índice global
Cómo se puntúa
36/36Recencia de push — último push hace 3 días
6.9/36Cadencia de commits — 10/52 semanas con commits
16/18Volumen de commits — 60 commits en el último año
10/10OpenSSF Scorecard: Maintained — 30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10
Datos de entrada utilizados
commits_last_year60
human_commit_share1
days_since_last_push3
active_weeks_last_year10
Cómo se puntúa
27/27Publica versiones — 1 versiones publicadas
36/36Recencia de las versiones — última versión hace 3 días
12.6/27Cadencia de publicación — cadencia desconocida (una sola versión)
0/10OpenSSF Scorecard: Signed-Releases — sin datos
Datos de entrada utilizados
releases_count1
latest_release_tagv2.8.0
releases_from_tagsno
days_since_latest_release3
mean_days_between_releases
Excluidos de la puntuación (sin datos o no aplicable): OpenSSF Scorecard: Signed-Releases. Los pesos restantes se han renormalizado.

Comunidad y Adopción

¿Tiene el proyecto usuarios, descargas, atención y unas condiciones acogedoras para quienes contribuyen?

24Crítico · 18% del índice global
Cómo se puntúa
0/60Estrellas — 1 estrellas
0/25Forks — 0 forks
0/15Observadores — 0 observadores
Datos de entrada utilizados
forks0
stars1
watchers0
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Cómo se puntúa
22.5/22.5README
22.5/22.5Licencia — licencia reconocida (MIT)
0/18Guía CONTRIBUTING
0/13.5Código de conducta
0/7.2Plantilla de issues
0/6.3Plantilla de PR
Datos de entrada utilizados
has_readme
has_license
has_contributingno
has_issue_templateno
has_code_of_conductno
has_pull_request_templateno

Sostenibilidad y Gobernanza

¿Sobrevivirá el proyecto a sus personas: factor bus, capacidad de respuesta, quién lo respalda y mantenimiento del paquete?

46En riesgo · 24% del índice global
Cómo se puntúa
9/54Factor bus — la mitad de los commits recae en 1 contribuyente(s)
0/22.5Distribución de commits — el principal contribuyente firma el 100% de los commits
1.4/13.5Amplitud de contribuyentes — 1 contribuyentes
3/10OpenSSF Scorecard: Contributors — project has 1 contributing companies or organizations -- score normalized to 3
Datos de entrada utilizados
bus_factor1
contributors_sampled1
top_contributor_share1
Cómo se puntúa
0/46.8Resolución de issues — 0% de issues cerradas
35.5/38.3Aceptación de PR — 13/14 PR decididos fusionados
0/15OpenSSF Scorecard: Code-Review — Found 0/16 approved changesets -- score normalized to 0
Datos de entrada utilizados
merged_prs13
open_issues1
closed_issues0
issue_closed_ratio0
closed_unmerged_prs1
Cómo se puntúa
10/30Respaldo de la propiedad — cuenta personal (usuario)
0/20Dominio verificado — no aplicable a cuentas de usuario
8/25Alcance del propietario — 12 seguidores de zach-source
25/25Trayectoria — 90 repos públicos, cuenta de ~6 años
Datos de entrada utilizados
followers12
owner_typeUser
is_verified
owner_loginzach-source
public_repos90
account_age_days2336
Excluidos de la puntuación (sin datos o no aplicable): Dominio verificado. Los pesos restantes se han renormalizado.
Cómo se puntúa
25/25Publicado y resoluble — 1 paquete(s) en go
35/35Recencia de publicación — última publicación hace 114 días
20/20Historial de versiones — 17 versiones en el registro
20/20No obsoleto — activo, ni obsoleto ni retirado
Datos de entrada utilizados
packagesgithub.com/zach-source/ccswitch
ecosystemsgo
any_deprecatedno
min_days_since_publish114

Calidad de Ingeniería

¿Existen unas prácticas mínimas de ingeniería y documentación?

44En riesgo · 20% del índice global
Cómo se puntúa
0/24Flujos de trabajo de CI
24/24Pruebas presentes
0/16Configuración de linter
0/9.6Hooks de pre-commit
0/6.4.editorconfig
0/20OpenSSF Scorecard: CI-Tests — 0 out of 13 merged PRs checked by a CI test -- score normalized to 0
Datos de entrada utilizados
has_cino
has_tests
has_editorconfigno
has_linter_configno
has_precommit_configno
Cómo se puntúa
30/30README
25/25Directorio de documentación
0/15Sitio de documentación / página del proyecto
10/10Descripción del repositorio
0/10Topics
10/10Wiki
Datos de entrada utilizados
topics
has_wiki
homepage
has_readme
has_docs_dir
has_description

Seguridad

¿Son sólidas las prácticas visibles de seguridad y de cadena de suministro, sin exposición jurisdiccional de alto riesgo sin resolver?

29Crítico · 16% del índice global
Cómo se puntúa
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 — sin datos
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5Licencia — 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 — sin datos
0/5Pinned-Dependencies — sin datos
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 — sin datos
0/7.5Token-Permissions — sin datos
0/7.5Vulnerabilities — 25 existing vulnerabilities detected
Datos de entrada utilizados
sourceopenssf_scorecard
checks_evaluated13
scorecard_versionv5.5.0
checks_inconclusive5
scorecard_aggregate2,9
Excluidos de la puntuación (sin datos o no aplicable): dangerous_workflow, packaging, pinned_dependencies, signed_releases, token_permissions. Los pesos restantes se han renormalizado.

Preparación para IA

¿Hasta qué punto está el repositorio preparado para desarrollarse y mantenerse con agentes de codificación de IA? Es una insignia independiente y experimental — peso 0,0, de modo que se presenta por separado y no afecta a la puntuación de salud global.

64Moderado · 0% del índice global
Cómo se puntúa
0/45Instrucciones para agentes — sin CLAUDE.md / AGENTS.md / reglas de editor
0/15Documentación legible por máquinas (llms.txt)
40/40Historial de commits legible — 60 de 60 commits humanos declaran su intención (asunto estructurado o cuerpo explicativo)
Datos de entrada utilizados
has_llms_txtno
legible_history_share1
agent_instruction_files
agent_instruction_max_bytes
Cómo se puntúa
18/18Arranque con un solo comando — Makefile
22/22Pruebas automatizadas
0/11Configuración de lint / formato
11/11Verificación estática de tipos — Go (tipado estático)
10/10Entorno reproducible — Nix, lockfile
0/10Práctica demostrada con agentes — ningún commit con autoría de agente entre los últimos 60
0/8Mantenimiento automatizado — no se observan actualizaciones automáticas de dependencias
0/10OpenSSF Scorecard: Pinned-Dependencies — sin datos
Datos de entrada utilizados
has_nix
has_tests
lockfilesgo.sum
has_dockerfileno
typed_language
bootstrap_filesMakefile
has_devcontainerno
has_linter_configno
typecheck_configs
agent_commit_share0
toolchain_manifestsgo.mod
dependency_bot_commit_share0
Excluidos de la puntuación (sin datos o no aplicable): OpenSSF Scorecard: Pinned-Dependencies. Los pesos restantes se han renormalizado.
Cómo se puntúa
45/45Código verificable por tipos — Go (tipado estático)
55/55Tamaños de archivo manejables — 0/67 archivos fuente de más de 60 KB
Datos de entrada utilizados
primary_languageGo
largest_source_bytes18.504
source_files_sampled67
oversized_source_files0

Datos clave

1estrellas de GitHub
1contribuidores
60commits en los últimos 12 meses
3días desde el último push
1versiones publicadas
1factor bus
1issues abiertas
Goecosistemas de paquetes

Advertencias de recopilación de datos

  • 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

Más detalle

OpenSSF Scorecard 2.9 / 10
2.9agregado

Evaluación de seguridad independiente y agnóstica en cuanto a herramientas, procedente del proyecto de código abierto OpenSSF Scorecard. Cada comprobación premia una práctica de seguridad, no la herramienta de un proveedor concreto. Las comprobaciones que Scorecard no pudo determinar se marcan como n/d y se excluyen de la puntuación de seguridad (nunca se cuentan como cero).Scorecard v5.5.0 · 2026-07-29 21:23 UTC

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
0CI-Tests0 out of 13 merged PRs checked by a CI test -- score normalized to 0
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/16 approved changesets -- score normalized to 0
3Contributorsproject has 1 contributing companies or organizations -- score normalized to 3
n/dDangerous-Workflowno workflows found
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
10Maintained30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10
n/dPackagingpackaging workflow not detected
n/dPinned-Dependenciesno dependencies found
0SASTSAST tool is not run on all commits -- score normalized to 0
4Security-Policysecurity policy file detected
n/dSigned-Releasesno releases found
n/dToken-PermissionsNo tokens found
0Vulnerabilities25 existing vulnerabilities detected
Dependencias directas 5
RegistroPaqueteRestricción de versiónManifiesto
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
Todas las dependencias no recopilado

No fue posible recopilar el conjunto de dependencias resuelto para este informe: GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

Informe JSON sin procesar legible por máquina
{
  "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"
}

Las puntuaciones son señales, no garantías. Reflejan prácticas públicamente visibles en GitHub; no son una auditoría de código ni una garantía de seguridad.

Los datos ausentes se excluyen y los pesos se renormalizan; nunca se puntúan como cero. La metodología es versionada y abierta: métricas v1.13.0, esquema v0.27.0 — metodología completa · wiki de métricas.

Cómo se sitúa un resultado dentro del registro general: estadísticas agregadasGo.