Registro público
Informe de salud del softwareesquema 0.27.0 · métricas 1.13.0 · 2026-07-25 12:41 UTC

jsdvjx / ccfly

Code anywhere — npx control+terminal server for Claude Code (tmux) + @ccfly/react; self-hosted /term WS, no ttyd.

Go · TypeScriptMIT★ 1 estrella⑂ 0 forksdesde jun 2026Ver en GitHub ↗

jsdvjx/ccfly tiene un índice de salud de 43 sobre 100, lo que lo sitúa en la banda En riesgo. Su puntuación más alta es AI Readiness (73/100) y la más baja, Community & Adoption (24/100). Se actualizó por última vez hace 5 días. Una sola persona concentra la mayor parte del trabajo reciente.

43
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.

43
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

jsdvjxCuenta personal
1 seguidor5 repositorios públicosdesde may 2015

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/jsdvjx/ccflyv0.3.10-3hace 48 días

Métricas por categoría

Vitalidad

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

71Bueno · 22% del índice global
Cómo se puntúa
36/36Recencia de push — último push hace 5 días
5.5/36Cadencia de commits — 8/52 semanas con commits
18/18Volumen de commits — 129 commits en el último año
0/10OpenSSF Scorecard: Maintained — project was created within the last 90 days. Please review its contents carefully
Datos de entrada utilizados
commits_last_year129
human_commit_share1
days_since_last_push5
active_weeks_last_year8
Cómo se puntúa
16.2/27Publica versiones — 3 etiquetas de versión (sin releases de GitHub)
36/36Recencia de las versiones — última versión hace 48 días
27/27Cadencia de publicación — una versión cada ~0,1 días
0/10OpenSSF Scorecard: Signed-Releases — sin datos
Datos de entrada utilizados
releases_count3
latest_release_tagv0.3.10
releases_from_tags
days_since_latest_release48
mean_days_between_releases0,1
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?

31En 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
0/10OpenSSF Scorecard: Contributors — project has 0 contributing companies or organizations -- score normalized to 0
Datos de entrada utilizados
bus_factor1
contributors_sampled1
top_contributor_share1
Cómo se puntúa
0/46.8Resolución de issues — sin issues o sin datos
0/38.3Aceptación de PR — sin PR decididos o sin datos
0/15OpenSSF Scorecard: Code-Review — Found 0/30 approved changesets -- score normalized to 0
Datos de entrada utilizados
merged_prs0
open_issues0
closed_issues0
issue_closed_ratio
closed_unmerged_prs0
Excluidos de la puntuación (sin datos o no aplicable): Resolución de issues, Aceptación de PR. Los pesos restantes se han renormalizado.
Cómo se puntúa
10/30Respaldo de la propiedad — cuenta personal (usuario)
0/20Dominio verificado — no aplicable a cuentas de usuario
2.2/25Alcance del propietario — 1 seguidores de jsdvjx
17.7/25Trayectoria — 5 repos públicos, cuenta de ~11 años
Datos de entrada utilizados
followers1
owner_typeUser
is_verified
owner_loginjsdvjx
public_repos5
account_age_days4097
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 48 días
12/20Historial de versiones — 3 versiones en el registro
20/20No obsoleto — activo, ni obsoleto ni retirado
Datos de entrada utilizados
packagesgithub.com/jsdvjx/ccfly
ecosystemsgo
any_deprecatedno
min_days_since_publish48

Calidad de Ingeniería

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

56Moderado · 20% del índice global
Cómo se puntúa
24/24Flujos de trabajo de CI — 2 flujo(s) de trabajo
24/24Pruebas presentes
0/16Configuración de linter
0/9.6Hooks de pre-commit
0/6.4.editorconfig
0/20OpenSSF Scorecard: CI-Tests — sin datos
Datos de entrada utilizados
has_ci
has_tests
has_editorconfigno
has_linter_configno
has_precommit_configno
Excluidos de la puntuación (sin datos o no aplicable): OpenSSF Scorecard: CI-Tests. Los pesos restantes se han renormalizado.

Documentación

50Moderado
Cómo se puntúa
30/30README
0/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_dirno
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?

25Crí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 — sin datos
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/30 approved changesets -- score normalized to 0
0/2.5Contributors — project has 0 contributing companies or organizations -- score normalized to 0
10/10Dangerous-Workflow — no dangerous workflow patterns detected
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5Licencia — license file detected
0/7.5Maintained — project was created within the last 90 days. Please review its contents carefully
0/5Packaging — sin datos
0/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
0/5SAST — no SAST tool detected
0/5Security-Policy — security policy file not detected
0/7.5Signed-Releases — sin datos
0/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
2.2/7.5Vulnerabilities — 7 existing vulnerabilities detected
Datos de entrada utilizados
sourceopenssf_scorecard
checks_evaluated15
scorecard_versionv5.5.0
checks_inconclusive3
scorecard_aggregate2,5
Excluidos de la puntuación (sin datos o no aplicable): ci_tests, packaging, signed_releases. 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.

73Bueno · 0% del índice global
Cómo se puntúa
45/45Instrucciones para agentes — CLAUDE.md
0/15Documentación legible por máquinas (llms.txt)
40/40Historial de commits legible — 98 de 100 commits humanos declaran su intención (asunto estructurado o cuerpo explicativo)
Datos de entrada utilizados
has_llms_txtno
legible_history_share0,98
agent_instruction_filesCLAUDE.md
agent_instruction_max_bytes10.363
Cómo se puntúa
12.6/18Arranque con un solo comando — go/go.mod (convención del toolchain, sin ejecutor de tareas)
22/22Pruebas automatizadas
0/11Configuración de lint / formato
11/11Verificación estática de tipos — examples/web/tsconfig.json, packages/react/tsconfig.json
10/10Entorno reproducible — Dockerfile, lockfile
10/10Práctica demostrada con agentes — 80 de los últimos 100 commits con autoría o crédito de agente
0/8Mantenimiento automatizado — no se observan actualizaciones automáticas de dependencias
0/10OpenSSF Scorecard: Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
Datos de entrada utilizados
has_nixno
has_tests
lockfilesgo.sum, pnpm-lock.yaml
has_dockerfile
typed_language
bootstrap_files
has_devcontainerno
has_linter_configno
typecheck_configsexamples/web/tsconfig.json, packages/react/tsconfig.json
agent_commit_share0,8
toolchain_manifestsgo/go.mod
dependency_bot_commit_share0
Cómo se puntúa
45/45Código verificable por tipos — Go (tipado estático)
55/55Tamaños de archivo manejables — 0/226 archivos fuente de más de 60 KB
Datos de entrada utilizados
primary_languageGo
largest_source_bytes51.187
source_files_sampled226
oversized_source_files0
Cómo se puntúa
0/40Esquema de API (OpenAPI/GraphQL/proto)
0/20Servidor MCP
40/40Ejemplos ejecutables — examples
Datos de entrada utilizados
example_dirsexamples
has_mcp_signalno
api_schema_files

Datos clave

1estrellas de GitHub
1contribuidores
129commits en los últimos 12 meses
5días desde el último push
3versiones publicadas
1factor bus
0issues abiertas
Go, npmecosistemas 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.5 / 10
2.5agregado

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-25 12:41 UTC

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
n/dCI-Testsno pull request found
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/30 approved changesets -- score normalized to 0
0Contributorsproject has 0 contributing companies or organizations -- score normalized to 0
10Dangerous-Workflowno dangerous workflow patterns detected
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
0Maintainedproject was created within the last 90 days. Please review its contents carefully
n/dPackagingpackaging workflow not detected
0Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 0
0SASTno SAST tool detected
0Security-Policysecurity policy file not detected
n/dSigned-Releasesno releases found
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
3Vulnerabilities7 existing vulnerabilities detected
Dependencias directas 11
RegistroPaqueteRestricción de versiónManifiesto
Gogithub.com/UserExistsError/conptyv0.1.4go/go.mod
Gogithub.com/coder/websocketv1.8.14go/go.mod
Gogithub.com/coredns/caddyv1.1.4-0.20250930002214-15135a999495go/go.mod
Gogithub.com/coredns/corednsv1.14.6go/go.mod
Gogithub.com/creack/ptyv1.1.24go/go.mod
Gogithub.com/fsnotify/fsnotifyv1.10.1go/go.mod
Gogithub.com/miekg/dnsv1.1.72go/go.mod
Gogolang.org/x/cryptov0.53.0go/go.mod
Gogolang.org/x/sysv0.47.0go/go.mod
Gogolang.org/x/termv0.44.0go/go.mod
Gogolang.zx2c4.com/wireguardv0.0.0-20260522210424-ecfc5a8d5446go/go.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": 2347,
      "has_wiki": true,
      "homepage": null,
      "languages": {
        "Go": 822692,
        "CSS": 107208,
        "HTML": 1507,
        "NSIS": 8490,
        "Shell": 32698,
        "Dockerfile": 4569,
        "JavaScript": 6717,
        "PowerShell": 1699,
        "TypeScript": 595638
      },
      "pushed_at": "2026-07-20T11:37:19Z",
      "created_at": "2026-06-05T06:38:05Z",
      "owner_type": "User",
      "updated_at": "2026-07-20T11:37:56Z",
      "description": "Code anywhere — npx control+terminal server for Claude Code (tmux) + @ccfly/react; self-hosted /term WS, no ttyd.",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "MIT",
      "default_branch": "main",
      "license_spdx_raw": "MIT",
      "primary_language": "Go",
      "significant_languages": [
        "Go",
        "TypeScript"
      ]
    },
    "owner": {
      "blog": null,
      "name": null,
      "type": "User",
      "login": "jsdvjx",
      "company": null,
      "location": null,
      "followers": 1,
      "avatar_url": "https://avatars.githubusercontent.com/u/12291665?v=4",
      "created_at": "2015-05-07T07:36:04Z",
      "is_verified": null,
      "public_repos": 5,
      "account_age_days": 4097
    },
    "license": {
      "state": "standard",
      "spdx_id": "MIT",
      "raw_spdx": "MIT",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v0.3.10",
          "kind": "patch",
          "published_at": "2026-06-06T15:51:33Z"
        },
        {
          "tag": "v0.3.9",
          "kind": "patch",
          "published_at": "2026-06-06T10:02:04Z"
        },
        {
          "tag": "v0.3.8",
          "kind": "patch",
          "published_at": "2026-06-06T09:50:29Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "a4ba628519d56bdcb35911778eaa7a38b43d67cd",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): ccfly 0.18.0",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-19T14:48:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "316a7a3fea5ddccff8e2de1b1e352ff372ab6069",
          "body": "- 新增 dnsPolicyService(dnspolicy.go):DNS 服务自己周期拉 OSS domainlist、热重载 CoreDNS,\n  三端同一份;首拉失败用编译期兜底,坏拉取保留旧版\n- Windows:hosts 精确钉 → 网卡 DNS 指 127.0.0.1 + 次级上游(备份/恢复,fail-open);\n  删除 hosts 写块路径(保留旧块剥离用于卸载清理)\n- macOS:root helper 常驻自持策略服务,arm 只传 relay_port;清单热更新自动重写\n  /etc/resolver(不再需要 agent 下发/重装);arm 应答携带清单版本\n- agent 不再拉取/分发域名清单;sameSNI 不再比较 intercept/upstream(与 cloud 解耦);\n  版本上报:linux/windows 读进程内服务,darwin 读 resolver 实况 + HEAD 观测 ETag",
          "is_bot": false,
          "headline": "feat(mesh): 三端统一 SNI 拦截为内嵌 DNS on :53,策略服务自持 OSS 清单",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-19T14:47:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2fe53134ac7b896280948e62ce9ee8742f46c848",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): ccfly 0.17.0",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-19T11:17:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fc7dd5a712bb5c9645137c56ed5a257424abd062",
          "body": "refreshConfig 与 runSNIPolicyRefresher 均触发 OSS 清单独立收敛:已有 arm 立即重装,\n新连接只预热缓存;兑现 ec8303d revert 时『随 sni.go 一起落地』的承诺。",
          "is_bot": false,
          "headline": "fix(mesh): 接上 SNI 域名清单刷新(refreshDomainListAndRearm 两处调用点)",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-19T11:15:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8c2ec13db1d5107cc683ab26d241ccc5b5cee9bc",
          "body": "- 本机 claude auth login 持有完整 OAuth,BROWSER 指回 ccfly 自身吞掉授权 URL\n- URL 发云端 /api/device/login/cdp/*,eu-control manual-oauth 固定身份云浏览器过授权\n- 一次性 code#state 回填本地落盘;不带 email 生成 30min 网页选号票据\n- 旧库存凭据模式保留为显式 --credential,--auto 不变,--cdp 兼容别名",
          "is_bot": false,
          "headline": "feat(login): claude login 默认改 Cloud-CDP OAuth(云浏览器代授权)",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-19T11:14:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7857dd07fdfea8298f472e10bbe9b1557a005ce8",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): ccfly 0.16.0 — mesh 有序多入口 failover(回填隔离发布树的版本号)",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-19T11:13:28Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0d43d0d40fbf9380ccefd2cfa73d222ae00d009a",
          "body": "- MeshEndpoint{url,dial_addr}:url 作 WS Host 与证书身份,dial_addr 可选改 TCP 目的\n- CCFLY_MESH_ENDPOINTS 环境列表优先,云端 mesh_url 永远作最终兼容回退\n- State/connectResp/deviceConfig 增加 mesh_endpoints,入网与配置刷新下发即更新\n- 拨号覆写克隆独立 HTTP Transport 并禁用代理,避免覆写被 CONNECT 旁路、token 泄漏",
          "is_bot": false,
          "headline": "feat(mesh): 有序多入口 failover,TLS 身份 URL 与实际拨号地址分离",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-19T11:10:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "992a1189c9b8c4304b628c01940bf2d49fb3b28f",
          "body": "…ckfile)",
          "is_bot": false,
          "headline": "fix(release): 同步 pnpm-lock 与 cli 0.15.5 平台包钉版(修 release.yml frozen-lo…",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-19T10:01:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "70d0d899016621bc8dd1bbbd59d5f5454bea10f5",
          "body": "数据面:进程内 CoreDNS(仅 bind/template/forward)接管 :53,intercept 域合成\nloopback、其余转 OSS 上游;macOS 改 scoped /etc/resolver + root helper 持租约\n(控制连接 EOF 即撤 resolver/停 CoreDNS/关 :443,拒绝覆盖用户已有 resolver);\nWindows 仍 hosts 精确钉、Linux resolv.conf 备份恢复。OSS 域名清单 ETag 热更新,\ndeploy-device.sh 按「先 helper 后 agent」重启。\n\n检测:拆「组件自检」\n[…]\nlved_addresses 与 error_code。\n检测调度:arm 即检、正常 30s、失败退避 2/5/10/30s、WG 与配置变化立即重检、\n45s 过期按 checking 不标记健康。\n\n同时修正三个被本机 /etc/hosts 残留钉死记录骗坏的测试(探测名换用不在 hosts\n里的拦截子域、TestDarwinResolverScoped 打桩 unixHostsPath)。",
          "is_bot": false,
          "headline": "feat(mesh): SNI 数据面 — CoreDNS scoped 拦截、helper 租约与真实应用路径检测",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-19T09:31:50Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ec8303d59116a178d9e67936fc1175da336d8d18",
          "body": "Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "revert(mesh): 摘除误入 e785d8a 的 SNI domainlist WIP 调用点(随 sni.go 一起落地)",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-18T01:44:58Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "cb2bb34f659c6dae51e5efdd33be8c1c4304993c",
          "body": "Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(release): ccfly 0.15.5 — agent 云端链路免疫环境代理",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-18T01:40:50Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e785d8a27ebd81250dc5f9334e36cdc3e955b2f7",
          "body": "配对/控制面/mesh WSS/会话同步/claude login 全部换用 internal/cloudhttp\n的无环境代理客户端。Windows 客户注册表残留的持久代理变量会把计划任务里\n的 connect 导进已退出的本地代理(交互 shell 配对成功、任务却稳定 EOF),\n且任务环境从注册表重建、与 shell 不同步,极难排查。\n\n确需经代理接入云端的部署用 CCFLY_PROXY=<url> 显式指定;UI 包下载(npm\nregistry)等非云端链路仍走环境代理。\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(mesh): agent 云端链路不再吃 HTTP(S)_PROXY 环境变量,一律直连",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-18T01:38:30Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "25c034d8571907c3a4580d7eac5f07eadd973d97",
          "body": "- svc: Linux install 检测不到 systemd(容器/精简系统)时不再硬失败,\n  改为 setsid 后台直启 agent 并提示如何持久化;Windows/unix 各自补齐\n  startDetachedAgent 实现\n- hostagent: 新增 POST /clear-data,清实例工作区/Claude 会话/上传缓存\n  后重启容器(保留接入身份,同 device id 干净重上线),附 agent_test.go\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(svc): 无 systemd 环境安装回退 + hostagent clear-data",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-18T00:40:29Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "c1db5e4001b287c4a8262240cbdab54423a64c1d",
          "body": null,
          "is_bot": false,
          "headline": "fix(release): reuse committed webdist in clean builds",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-16T01:05:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6752a22ec79bfce9832ab942e83500747357c742",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): ccfly 0.15.4 browser handoff",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-16T01:01:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "630d8a173457cee483413e7151aa7dd5cf2f9d13",
          "body": null,
          "is_bot": false,
          "headline": "feat(claude): add browser auto-login handoff",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-15T15:09:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "05bc3d6d85364cdde542e8ff8d14f27787c05b6a",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): ccfly 0.15.3 SNI hardening",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-15T12:17:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "440ad80a7499309609e299eb37a2311326f8017a",
          "body": "0.11.0 之后累积的 npm 发版(0.13.0 内置 tmux、0.15.x SNI helper/\n邀请组真机验证等)版本号与 CHANGELOG 对齐到已发布的 0.15.2;\n内嵌 web 资产同步为 0.1.0 构建产物。\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(release): ccfly 0.15.2 版本与 changelog + webdist 0.1.0",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-14T23:10:34Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "b3fdb5a32b2e449da3b42a2f4edd8b17e9ccf2b7",
          "body": "两处 flap 根因修复:\n- WG bind 每帧收发盖 lastAct 时间戳;keepalive pong 超时且 45s 内有真实\n  流量则不自杀——设备大流量上传时自己的 ping 会饿死在 WS 写锁后面,\n  误判半开把活隧道拆掉正是 2026-07 的规律闪断。Send 自带 10s 写超时\n  仍兜底真卡死的 socket。\n- 存活超 1 分钟的连接断开视为稳定连接闪断,退避重置 1s 立即重连;\n  此前退避从不重置,晚高峰跨境限速被踢一次就固定吃满 30s 掉线体感。\n  短命连接照常翻倍退避,重连风暴保护不变。\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(mesh): keepalive 以真实流量判活 + 长命连接闪断快速重连",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-14T23:10:34Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "42fb3131041c01c6eb455796b7625840ca54e936",
          "body": "macOS 用 makensis 交叉构建 ccfly-setup-x64.exe:安装器只铺文件+PATH\n(服务注册仍靠 ccfly install,升级须重跑);deploy 脚本推 cc.hn/dl/。\n图标由 webdist PNG 构建期生成,进 .gitignore。\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(win): NSIS 安装包构建/部署脚本",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-14T23:10:15Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "c2269a906f71936758783dc224b00608fd4ca9c6",
          "body": "macOS 上 claude-code 以登录钥匙串(非 ~/.claude/.credentials.json)为\nOAuth 主源,文件凭据会被钥匙串旧凭据遮蔽。写凭据时放一次性\nkeychain-seed-pending 标记,下次起/重载 claude 会话时经 wrapClaudeCmd\n在已解锁的 tmux 用户上下文把凭据写进钥匙串(keychain_darwin.go);\n非 darwin 全程 no-op。\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(darwin): claude 订阅凭据 seed 进登录钥匙串",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-14T23:10:15Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "904c1b7b6efceb750d90cfd7f660682f3ec12041",
          "body": "macOS 非 root agent 绑不了 :443/写不了 /etc/hosts,SNI 本质起不来:\n- 拆双进程:root helper LaunchDaemon(com.ccfly.sni-helper,隐藏子命令\n  ccfly sni-helper)只绑 :443 splice 回 agent 非特权 relay 端口 + 写\n  /etc/hosts 免 :53;overlay 拨号仍留 agent 进程(netstack 不可跨进程)。\n- install/uninstall 硬闸门:macOS 要求 root 且 agent 装成 system\n  LaunchDaemon\n[…]\nnthropic.com 主动探测),mesh 摘要推送带 sni 状态\n  (未 arm 也上报,云端可分「未生效」vs「从未上报」)。\n\ninstall 侧顺带接上内置 tmux 落盘(servicePATH bundled 分支→EnsureAt)。\n三平台编译+真机集成测试通过。\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(sni): macOS root helper 双进程 + 三平台解析指向 + arm 状态自检/上报",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-14T23:10:01Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a97f03365fb3547410498e0e12661728e6293700",
          "body": "internal/tmuxbin 把可移植 tmux(libevent/ncursesw 静态链,blob 由\nscripts/build-tmux-macos.sh 生成并提交进仓库)go:embed 进 darwin 构建。\n运行时 ensureToolPath 尾部找不到系统 tmux 才释放到 ~/.ccfly/bin 并前置\nPATH;系统 tmux 永远优先(跨版本 client/server protocol mismatch,不能\n抢用户在跑的 server)。default-terminal 编译期定为 screen-256color。\nLinux 不内嵌(Bundled()=false 空操作);Windows 另有 psmux 路径。\n\ninstall 侧的 servicePATH bundled 分支随后续 svc.go 变更一并提交。\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(darwin): 内置静态 tmux 3.5a,系统未装 tmux 时自动兜底",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-14T23:09:33Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "64d1f221a4c368787b97221d0bdc21656adb17ac",
          "body": "…→ byway-sni)\n\n已发布 npm:主包 ccfly@0.11.0 + 5 平台子包(darwin/linux arm64+x64, win32-x64)。\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(release): ccfly@0.11.0 — SNI 客户端(DNS 三平台指向 + 本地 :443 → overlay …",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-13T06:54:07Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "ec7067970e9f08a35147553ecb59be9f90adc1d0",
          "body": "Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(sni): 更新 changeset——DNS 指向三平台已全实现",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-13T06:36:50Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "690f8848f254f8523b13fdb6db85f37837fa45f1",
          "body": "…solv.conf)\n\n之前只 Linux 改 resolv.conf、mac/win 留 no-op;现三平台都真正把系统解析指向本地 SNI DNS:\n- macOS:/etc/resolver/<域> scoped —— 每个 intercept apex 域一个文件(nameserver 127.0.0.1\n  + ccfly 标记),只把这些域(含子域)路由到本地,不动全局 resolver;卸载按标记精确清理\n  (保留用户自己的 resolver 文件,能清重启遗留)。\n- Windows:NRPT scoped —— 每个域一条 `.<域>` 规则(-NameServers \n[…]\nlver/restoreResolver 统一接口。\nsetupLocked 对所有平台统一调 pointResolver(intercept,upstream),不再按 GOOS 分支 no-op。\ndarwin scoped 逻辑单测(临时目录,免 root);5 平台交叉编译全过。\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(sni): DNS 指向三平台全实现(macOS /etc/resolver + Windows NRPT + Linux re…",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-13T06:36:22Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "48ca5cb5a4f36ca48eb92529f907223e7866f1c2",
          "body": "Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(sni): changeset for client SNI arm (minor)",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-13T06:25:10Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "bafdd4f73ea77afc290ec1e171f1a925e56db8d6",
          "body": "据云端 GET /api/device/config 的 sni 段驱动(有段→装,无段→幂等卸载):\n- 内嵌极小 DNS(127.0.0.1:53):intercept 域(含子域)→ A=127.0.0.1/AAAA=::1,\n  其余原样转上游阿里 —— 比外部 SmartDNS 轻,ccfly 本就是 Go 进程。\n- 本地 :443 双栈监听 → 经当前 WG 会话 netstack 透传到账号出口 byway-sni\n  (activeNet 由 bringUpWG 发布;overlay 未就绪则丢连接 fail-open)。\n- Linux 改 resolv.conf 指向本地\n[…]\n接前 refreshConfig+applyMeshProxy+applyMeshSNI:登录后\n  云端新绑 sni 账号无需重启即生效;进程退出 defer 卸载(恢复 resolv.conf)。\n- 未收到 sni 段 → 完全 dormant,零回归。DNS 协议层逻辑单测全绿。\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(sni): 第⑥步 客户端 SNI arm(内嵌 DNS 拦截 + 本地 :443 经 overlay 透传)",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-13T06:16:59Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "52bf305d54ca26b9b680af4a97bc6d11c7e05f67",
          "body": "Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Version Packages 0.10.12",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-11T08:05:59Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "28ba2f8e9afb97d4dfd4651743d18f71e9bf1bd2",
          "body": "/sessions 扫描过去对每个变动会话重读整个 jsonl:几百 MB 的活跃会话每 20s 被\nsyncer + 每个 /sessions 请求各重读一遍(~756MB/分钟),是 ccfly connect CPU 常驻\n30%+ 的根因(james 机实测)。\n\n改为增量:scanCacheEntry 加 off(已消费到的行边界偏移),append-only 文件增长时\n只读新尾 [off, EOF) 并从上次快照累进(scanOneSession 拆成 scanSession/scanFrom/\napplyEvent;readLineCapped→readLineAt 追踪字节偏移)。成本从「读全文」降到「读新增\n几 KB」,不再随会话变大恶化。增量与全量逐字段一致、半截行不重不漏(新增回归测试)。\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "perf(control): 会话扫描增量化,消除活跃大会话每轮重读整文件的 CPU 开销",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-11T08:05:37Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "7831a865050c13c6d6ce311e35ebe38a62d705ed",
          "body": "Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Version Packages 0.10.11",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-09T09:05:08Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d5019a209c3de8ac9902d241dc5698c3ed042bf1",
          "body": "新增 POST /close 端点:接受 {sessions:[sid...], force:bool},逐个\nkill tmux 会话释放 CPU/内存;非 force 时守卫活跃(attached)、生成中\n(busy)、交互菜单(select)的会话,返回 closed/skipped 明细。\n/sessions 新增 bytes 字段(零额外 syscall,复用 scan 已有 size)。\n\nmesh 接收云端 can_use_claude/proxy/mesh 三态准入标志,nil=放行;\nclaude_login 在命令行层面门控(真正鉴权仍在云端 403)。\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(control): POST /close 批量关闭会话 + 内部功能准入闸",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-09T09:04:25Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "02e049e1a7509132940df1e6786edac52f2b87f6",
          "body": "根因:claude 官方原生安装器把二进制装在 ~/.local/bin,不在系统 PATH。\nccfly 守护跑在 launchd 下无 tty,ensureToolPath 的 `zsh -ilc` 交互探测\n失败 → 回落到缺 ~/.local/bin 的兜底 PATH → exec.LookPath(\"claude\") 与\ntmux 起会话都找不到 claude:/new 直起的 claude 秒退、/term·/start 的\n--resume 退化成裸 shell,前端屏判不出 → 会话恒「连接中」。\n\n修复:\n- 探测由单一 `-ilc` 改为 `-ilc`(有 tty 最全)失\n[…]\ntest.go(prepend / 幂等)。\n\n验证:去掉临时软链后接管离线会话仍 `claude --resume` 成功,证明守护自身\nPATH 已含 ~/.local/bin;已 build 0.10.10 装到本机守护并重启,网页新建/接管\n恢复正常。\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(control): 守护进程 PATH 补 ~/.local/bin,claude 找得到会话才起得来",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-07T06:33:13Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "76d99fda24ee9358577f52f17a22aadf20a9453e",
          "body": "发布 single-flight 会话扫描 + 单行上限补丁(消除 /sessions 缓存踩踏 OOM)。\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Version Packages 0.10.10",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-06T11:27:17Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "f4fbb1f856fa4b097a944e4abdf3c040ffed1be4",
          "body": "设备控制服务 /sessions 每个请求都全量扫描所有会话 jsonl;高并发下数百请求\n各自把全部 transcript 解析进内存,峰值 ×并发数 放大到数 GB(实测单机 315 并发\n把 ccfly 顶到 8G、swap 抖动拖垮整机)。\n\n- scanClaudeSessions 加 single-flight:一轮扫描进行中,并发调用等待并共享结果,\n  不再各扫一遍(抽出 doScanClaudeSessions + scanCall;scanBarrier 为测试 seam)。\n- scanOneSession 改用 jsonlLinesCapped 给单行设 1 MiB 上限:超大行截断跳过但不丢\n  后续行;全文渲染(transcript/subagents/图片)仍走 jsonlLines 无上限,不受影响。\n- 新增回归 claudescan_stampede_test.go:N 并发只跑一次真扫描 + 大行跳过保后续行。\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(control): single-flight 会话扫描 + 单行上限,消除 /sessions 缓存踩踏 OOM",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-06T11:04:33Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "4e57aad713b81c9ce60ba215c84d1cbe829aaafb",
          "body": "Windows 平台落地:\n- svc: Task Scheduler 安装(wrapper .cmd + vbs 隐藏阻塞启动、5 分钟自愈重复触发、\n  RestartOnFailure 生效);install 前强杀游离旧实例\n- npm 新增 ccfly-win32-x64 平台子包,build-binaries 捆绑 psmux(tmux for Windows)\n- /term 走 ConPTY 且隔离在 _termpty 桥子进程(ClosePseudoConsole 的 CTRL_CLOSE\n  连坐会静默杀死宿主服务,实测)\n- exec/signal/flock/proce\n[…]\ncript 未落盘的新会话\n  200 挂住轮询,消灭「连接中」死锁\n\n稳定性:\n- connect 单例:文件锁 + Windows 整机级命名互斥(跨用户 profile)\n- 服务态忽略 console interrupt;claude login 后台化 + status 子命令\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: Windows 全面支持 + 会话代理/稳定性根治(0.7.1 → 0.10.9)",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-07-03T01:52:49Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "56c54a87871238d71c922f24204185851237b058",
          "body": null,
          "is_bot": false,
          "headline": "release: ccfly 0.7.1",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-27T14:07:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f6573d5cd15f86a721651f661224bc8323dd5fd6",
          "body": "Published ccfly@0.7.0 + ccfly-{darwin,linux}-{arm64,x64}@0.7.0 to npm (lockstep fixed group).\n- feat(control): attn detection (permission/plan/choice → session attn_kind)\n- fix(control): canonical cc-<sid8> tmux naming + orphan-claude guard\n- fix(claudescan): recompute state on cache hit (working de\n[…]\nre: Go module → github.com/jsdvjx/ccfly; device deploy script + CI\n(@ccfly/react 0.4.5 + ccfly-webdist 0.1.0 unchanged → skipped.)\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release: ccfly 0.7.0",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-27T08:22:02Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "6e7aac10a28807aa6450557cdbac82280dd607a7",
          "body": "scripts/deploy-device.sh: build current-platform binary stamped with the packages/cli version, install over the LaunchDaemon agent, kickstart (fixes the 0.5.6->repo drift); --print-only/--no-restart. CI: go + TS build/test on PRs (npm publish stays in release.yml).\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(deploy): add device deploy script + CI",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-25T09:44:56Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "7ca74f1675968d1371182a9228e56e44003d60e1",
          "body": "Replace the placeholder github.com/ccfly/ccfly with the real remote github.com/jsdvjx/ccfly across go.mod, all internal imports, the two Dockerfiles' -ldflags profile.defaultMode path, and the doc notes. go build/vet/test all pass under the new path.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: rename Go module path to github.com/jsdvjx/ccfly",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-25T09:44:56Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9f6d256db7f36a4f72c3346312325f959ba3bdcc",
          "body": "项目已统一搬入 ~/ccfly-workspace/ 作为一级工作区;同步 CLAUDE.md 内的跨仓引用与系列总览路径。\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(CLAUDE.md): 路径迁移到 ~/ccfly-workspace",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-25T05:19:17Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9d667445cd6c06566a4b9ca447b8751ad581c805",
          "body": "- cmd/ccfly-hostd + internal/hostagent: 受 cloud 经 overlay 指挥 docker run 每用户实例\n\n- internal/profile: full/instance/host/restricted 能力档(只能加严)\n\n- docker/: 受限镜像 + 实例镜像与启动脚本; 根 Dockerfile/.dockerignore\n\n- mesh/forward/proxyenv/uisync/svc 配套调整\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: ccfly-hostd 主机代理 + 能力档 profile + 受限 Docker 实例镜像 + CLAUDE.md",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-25T05:11:09Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "597f1da559b5f1413dda2db56892621782e25077",
          "body": "根因:handleNew 用随机名 cc-<rand8> 起会话,前端按 sid 算 cc-<sid8> 连 /term,两者全靠\npanemap 真值表桥接。同 cwd 会话一多,真值表 miss 时启发式「n≥2 不猜」→ 解析不到 live →\nterm.go 的 cmd=\"claude\" 兜底就在 ccfly 进程 cwd(HOME)起个错目录的裸 claude,且不可被\nscanner 回收 → 雪崩堆积(实测 top.pm:/root 与 /root/assistant 各十余个孤儿 claude)。\n\n修复:\n- handleNew:拿到真 sid 后把 tmux 从随机名 re\n[…]\n回收的孤儿壳变成不可回收的孤儿 claude);保留\n  claudeResumeCmd(离线会话按原 cwd resume,单实例、不重复)。\n\n实测 top.pm:/new→cc-<sid8> 规范名 ✅ panemap 同步 ✅ /term 精确 attach 不再新增孤儿 ✅。\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(control): 新建会话规范 tmux 名为 cc-<sid8> + 撤裸 claude 兜底(根治接错会话/目录错/孤儿雪崩)",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-24T11:50:14Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d7412bdf4acd6def1131d36ea10c2b32889979be",
          "body": "…cays\n\ncachedScanOne cached the whole snapshot including the time-dependent State/AgeSec\nkeyed by file (mtime,size). A session that stops mid-\"working\" freezes its file,\nso the cache never re-ran classify and it reported \"working\" forever (both\n/sessions and the cloud syncer; AgeSec also froze into a fake \"just now\").\nRecompute classify/age on every cache hit using the cached parse — cheap, no\nextra file reads.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(claudescan): recompute session state on cache hit so \"working\" de…",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-22T05:42:40Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "56dcabfd771fb97398ccf8b453973bb093bd2bc5",
          "body": "Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release: ccfly 0.6.1 (tmux 会话设终端标题,多窗口可区分内容)",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-18T12:13:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "146f2e3d18e2804e1941f59001d37834df4786e6",
          "body": "ccfly a / new 启动会话时只 new-session,从不开 set-titles,外层终端标题\n全是 tmux 默认值 —— 开多个窗口根本分不清哪个跑哪个会话。\n\nattach 与 new 两条路径都在 new-session 命令串尾部内联(`;` 分隔,exec 直传\ntmux 无需 shell)两条 set-option:\n  - set-titles on            外层标题交给 tmux\n  - set-titles-string '#S'   标题=会话名;claude 设了 pane 标题再缀上 ` · <标题>`\n\n作用域限定到本会话(set-option -t <name>,非 -g),不动用户别处的 tmux;\npane_title 默认等于主机名时只显示会话名,避免缀上无意义的主机名。\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(ccfly): 给 tmux 会话设外层终端标题,多窗口可区分内容",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-18T12:12:56Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d33f1abd4c3f027181ad7c43df42b87df7b3c932",
          "body": null,
          "is_bot": false,
          "headline": "release: ccfly 0.6.0 (claude login 无 email 选号 + 按账号路由 + logout)",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-18T02:36:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "df7501c7c909dea78e6695d6ac8699dd8a75d7b4",
          "body": "ccfly claude logout 现在除清本地路由上下文外,还 POST /api/device/login/route/clear\n(对每个/指定云端),让云端清掉本设备的 sing-box 源路由 → 后续 claude 会话回退默认出网。\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(ccfly): claude logout 通知云端清按账号源路由",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-17T16:55:08Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "cbe13a3a1276d87c02cfe6de9f591a226de2e379",
          "body": "对接云端「账号共享 + 配额选号」:\n- claude login:--email 改可选(省略 → 云端在你可访问的共享账号里按 claude 用量+分配次数自动选号);\n  解析并展示分配结果(account_email/egress_v6/out_node_ip);403/503/409/401 中文提示。\n- 按账号 /128 路由:登录成功后把分配结果 + 云端下发的 account_proxy_url 落盘\n  ~/.ccfly/claude-login-<host>.json(0600);mesh.EnsureTmuxProxyEnv 改成优先级链 ——\n  有按账号代理 URL\n[…]\noverlay 代理;用户显式设的最优先。\n- ccfly claude logout:清路由上下文(不删 ~/.claude 凭证)。\n- 新增 mesh ClaudeLoginContext 存取 + 6 个测试;go build/vet/test 全过。\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(ccfly): claude login 无 email 选号 + 按账号 /128 路由 + logout",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-17T16:12:06Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f872c324d63f979a4738f592717bc529260d1a21",
          "body": "Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release: ccfly 0.5.9, @ccfly/react 0.4.5",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-16T16:51:01Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "52b20897f7b4966c81e042e50b50615a4645bc26",
          "body": "Background syncer riding the mesh control plane (not the WG tunnel): scan\n~/.claude jsonl, push summary docs + the appended tail to the cloud. The\ncloud's per-session byte high-water mark is the cursor, so the client keeps\nno local state. control exposes a read-only digest accessor; the uploader\nlives in mesh (control stays free of report logic).\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(sync): push local Claude sessions to the cloud",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-16T16:51:01Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "1bc0e40d0135544e3f111761ac1ab4bd41f78407",
          "body": "Decouple the web UI from the binary so UI changes ship via npm (publish ccfly-webdist) without rebuilding/republishing the platform binaries.\n\n- uisync.go: background checker (startup + hourly) queries registry.npmjs.org for ccfly-webdist; if newer than the embedded VERSION, downloads the tarball, v\n[…]\nkage version) + stages the npm publish source.\n- uisync_test.go: integrity, tar path-traversal, semver downgrade tests.\n\nTrust boundary = npm account + published SRI over HTTPS (same as the binaries).",
          "is_bot": false,
          "headline": "feat(ui): serve web UI from npm at runtime, embed only a fallback",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-16T16:33:35Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2b53aa7b0a90d08c4c9dd473c0345bda28515fe3",
          "body": "… title\n\nMake the read-screen → classify pipeline testable and pin its behavior, per\ndocs/state-engine.md §7/F6 (it previously had zero tests).\n\n- Extract the pure parser from engine.ts into pre.ts (zero xterm/React) and add\n  a pure classify(frame) seam, so detection is unit-testable and the tested\n[…]\nl\n  (\"--model.\") instead of the real title (\"Select model\").\n\nScope: @ccfly/react only; no Go / binary changes. Changeset: patch (0.4.4→0.4.5).\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test(engine): vitest harness for the screen-state engine + fix /model…",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-16T14:39:46Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "61dc9cf23c5053998b84121f63669bb5150824af",
          "body": null,
          "is_bot": false,
          "headline": "release: ccfly 0.5.8",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-16T10:05:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8b8de7fc8d1f20fc8a88f1cfeaf377c8e89c8c39",
          "body": "- Inject IS_SANDBOX=1 into a new session's tmux env when --dangerously-skip-\n  permissions is used and ccfly runs as root (uid 0); Claude Code otherwise\n  refuses skip-permissions under root. Covers ccfly new / picker, POST /new,\n  and offline resume (CLIAttachArgs). Non-root unchanged.\n- Pre-set ha\n[…]\nder\" dialog (which otherwise\n  blocks SessionStart and leaves the web /new without a session id). Defensive:\n  atomic write, no-op on any error.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(new): IS_SANDBOX for root + pre-trust chosen directory",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-16T10:05:40Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e2b4aee4191d645abc692ab1b14cc45d85e88b85",
          "body": null,
          "is_bot": false,
          "headline": "release: ccfly 0.5.7",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-16T09:26:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3b2d9205e044f8c53e73bc9191f9baaac451042f",
          "body": "`ccfly a` picker and `ccfly new` (no arg) now open a directory browser to pick\nthe new session's cwd (↑↓ / Enter / ← parent / n create-here / q cancel),\ncarrying the permission options. Two new local control endpoints back the web\nUI's new-session dialog: GET /dirs (list subdirectories) and POST /new (start a\nfresh claude detached in a cwd, poll the panemap, return the real session id).\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(new): choose directory via filesystem browser (a / new / web)",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-16T09:26:24Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "f5f5c22cf30796ae20517ccdf8995c48a630464f",
          "body": null,
          "is_bot": false,
          "headline": "release: ccfly 0.5.6",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-16T04:21:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "35285809b6e76e70008ba50065fa7a1577f028f1",
          "body": "Re-embeds ccfly-ttyd-ui so AskUserQuestion renders as an unfolded card\n(question + options + selected answer inline) instead of a collapsed generic\nJSON dump. No Go changes — webdist refresh + changeset only.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(web): dedicated AskUserQuestion card (re-embed web UI)",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-16T04:21:12Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d93a831c73be67fb5f7cdc9b4e6b58484c40424f",
          "body": null,
          "is_bot": false,
          "headline": "release: ccfly 0.5.5",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-16T03:35:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7d34c37cdc6ac0888c63c8d4a3ca093539701330",
          "body": "ccfly new and ccfly a now accept --permission-mode <default|acceptEdits|plan|\nbypassPermissions> and --dangerously-skip-permissions (alias --yolo), passed\nthrough to the launched claude. They apply on new sessions and offline resume;\nattaching to a live session leaves its mode untouched.\n\nThe intera\n[…]\nsid/dir,opts}; CLIAttachArgs/newSession thread\nthe claude args.\n\nAlso re-embeds the web UI so `!command` bash echoes render as IN/OUT/ERR cards.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(cli): new-session + permission options in new/attach/picker",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-16T03:34:52Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "86ddd3d08f2634ed4c36cd298454c3eb786367b5",
          "body": "refreshConfig silently returned on HTTP error / non-200 / bad JSON, which made\nit hard to diagnose why cloud-advertised config (proxy_port, proxy_ca) wasn't\napplying. Log each failure path; behaviour is unchanged (still degrades\ngracefully and keeps existing State). Changeset queued for the next release.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(mesh): log device-config refresh failures instead of swallowing",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-15T15:10:20Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d6930227f002f9071d89ed3a5172b4327380e64b",
          "body": "…0.5.4\n\nWhen the cloud advertises a TLS-bumping proxy exit (byway -bump), ccfly now\nreceives the exit's CA bundle in its device config (proxy_ca), writes it to\n~/.ccfly/proxy-ca.pem, and injects NODE_EXTRA_CA_CERTS into ccfly-created tmux\nsessions. Claude in a session then reaches AI endpoints throu\n[…]\n on the\ncenter heartbeat; ccfly-cloud stores it per out-node (out_config.ca_pem) and\nbundles all exit CAs into the device-config proxy_ca field.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(proxy): auto-trust mesh exit MITM CA in sessions; release ccfly …",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-15T14:19:02Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7b3c3f018ebe369ee5047311e344c6444be3be6f",
          "body": "设备连接时拉云端动态配置(/api/device/config):保存身份重连的设备也能拿到云端下发的出网代理\n策略与轮换后的云公钥,升级重启即零配置生效(不必改 State / 重新配对)。\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release: ccfly 0.5.3",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-15T04:15:17Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "5fbb654ce5d3b23bf6a0475ac2b9d1f9dd0e3ae7",
          "body": "runTunnel 起步先 GET /api/device/config(凭 mesh_token)刷新 cloud_public_key/overlay_ip\n与 proxy_port/scheme,落盘 State,再 applyMeshProxy。这样保存身份重连的设备(不重新 enroll)\n也能拿到云端后来才下发的代理策略、轮换后的云公钥 —— 升级二进制重启即生效,无需手动改 State\n或重新配对,真正做到「默认就启动、不需显式操作」。云端老版本/失败 → 沿用现有 State。\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(mesh): 连接时拉云端动态配置(refreshConfig)→ 代理策略真正零配置生效",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-15T04:14:59Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "f1b010234a754cc38f6b9ef3a2061383b83f97d2",
          "body": "云端下发出网代理策略 → 设备零配置自动起本地转发 + 给 ccfly 创建的会话注入代理 + 局域网 bypass\n环境(claude 起的 localhost 服务、局域网其它机器不被全局代理吞掉)。\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release: ccfly 0.5.2",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-15T03:58:33Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "274e56323055f572c7d6d3753418f7d3b76e8e0e",
          "body": "承接 696b4d7(会话代理环境注入):让「默认就启动、不需显式操作」真正成立。\n\n云端在入网响应里下发 proxy_port/proxy_scheme(运维设一次 CCFLY_CLOUD_PROXY_PORT 即全设备生效);\n设备(applyMeshProxy,入网/重连前一次性)据此零配置自动:\n  1) 起 127.0.0.1:<port> → <cloud_overlay_ip>:<port> 转发(addAutoForward,同 localPort 已配则跳过,\n     不覆盖用户 --overlay-forward);\n  2) 设 CCFLY_TMUX_PROXY=<sc\n[…]\ncfly 创建的会话默认带好\n     代理 + 局域网 bypass。\nProxyPort 持久化进 State:CLI(ccfly new/a,EnsureTmuxProxyEnv)与下次重连都据此自动配。\n云端未下发(ProxyPort==0)→ 全程 no-op,默认部署零影响。\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(mesh): 云端下发出网代理策略,设备零配置自动起转发 + 会话注入",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-15T03:56:42Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "696b4d7f4b1affc0291334a8a714a8f59e9c56ac",
          "body": "场景:出网流量经 ccfly 本地 forward(如 127.0.0.1:2080 → mesh 出口)代理。但全局代理会把\nclaude 起的 localhost 服务、局域网其它机器的请求也吞进 mesh → 够不到。\n\n让 ccfly 创建会话(new / attach / /term / /start 四处)时,默认经 tmux new-session -e 注入\nhttp(s)_proxy/all_proxy(大小写两套)+ no_proxy(loopback + RFC1918 私网 + link-local +\n*.local 直连),会话里 claude 及其子进程、用户手敲命令自动「出网走代理、本机/局域网直连」。\n\n开关:仅 CCFLY_TMUX_PROXY 配了代理 URL 才注入(未配零行为变化);CCFLY_TMUX_NO_PROXY 覆盖\nbypass 列表。需 tmux ≥ 3.2(-e)。\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tmux): ccfly 创建的会话默认注入代理 + 局域网 bypass 环境",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-15T03:37:34Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "ef0ce352fca2b0b2b0f10de236ec4e1ca2a9cb7e",
          "body": "mesh 数据面加固(根治「控制面在线、数据面静默死」复发):gateway Transport 重连淘汰 +\n上游超时、WG peer 删除 current 守卫、Send 写超时、presence 绑 AddPeer 成功。\ncontrol 包:并发图片 buffer 唯一名、网页终端粘贴读上限、jsonl 超大行不截断。\n内嵌 UI 同步 ttyd-ui(select/状态检测修复)。\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release: ccfly 0.5.1",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-15T02:44:18Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "eda659e3d2969b2327424f6390331d510633904d",
          "body": "clientWSBind.Send 原用 context.Background():TCP 发送缓冲写满 + 云端卡住时 c.Write 永久阻塞,\ncoder/websocket 写串行化 → 一个卡死的 Send 堵死后续所有 WG 握手/keepalive/数据 → WS 在线、\noverlay 数据不流(「在线却不通」)。改 10s 有界写超时 + 超时即 CloseNow 触发 pump 出错重连。\n与 ccfly-cloud 侧同一修复对称。\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(mesh): 设备侧 Send 有界写超时(M3)",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-15T02:39:09Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e9b0000cc1302a9a5b97f8b3d9d80418f6431ac1",
          "body": "A1 图片粘贴用全局共享 tmux buffer \"ccfly-img\"(写死名、无锁):两个会话/标签页\n  并发带图提交时互相覆盖 buffer → 粘成别人的图,或 -d 删后另一个 paste-buffer\n  报 no buffer 500 且输入行半填。改为每次请求生成唯一名 imgBufferName()(crypto/rand,\n  熵源故障回退进程内自增+纳秒),消除跨请求竞争。\n\nA6 /term WebSocket 沿用 coder/websocket 默认 32KiB 单帧读上限:网页终端粘贴一大段\n  (代码块/路径列表)超 32KiB 即触发读错误 → 读循环退出 \n[…]\n,go1.25 range-over-func),scanOneSession /\n  readSessionInfo / findMessageImage / scanRunningAgentsFrom 统一改用。\n\n回归测试覆盖超大行不截断 + 边界(空行/\\r\\n/半截行/早停)。\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(control): 并发图片 buffer 竞争 / 网页终端粘贴上限 / jsonl 超大行截断",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-15T01:59:58Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "059bf9c5f061b2082a8e6df1040f4ac47bae4ec0",
          "body": "panemap 真值表(根治消息错发)· stale 防护 · /sse/jsonl + follow 愈合 ·\nccfly ls/a/new/attach(交互式选择器)· takeover 防双写 · ccfly-mesh 组网\n客户端与 overlay 端口桥 · 内嵌 UI 切换为 ccfly-ttyd-ui。\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release: ccfly 0.5.0",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-13T01:02:26Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "7e3794daeb7e88e6848a42dd1a5354b2e89e86a5",
          "body": "节点端 go:embed 的 SPA 从旧 examples/web(React)切到 ccfly-ttyd-ui\n(Vue 双模:节点直连 base='';Hub 下 base='/x/<device>'),与 ccfly-cloud\n共用同一份构建产物。scripts/build-web.sh 改为从同级 ../ccfly-ttyd-ui 构建\n(CCFLY_TTYD_UI_DIR 可覆盖);examples/web 退役留档。\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(web): 内嵌 UI 切换为 ccfly-ttyd-ui",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-13T01:01:42Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "7aa37eebbbcabbdbe58bb2d7a63d5b844457a741",
          "body": "- ccfly-mesh:仅组网的精简客户端(sing-box 中心 / byway 出口等服务器用):\n  同一套网页配对入网、held WireGuard 隧道,不链入控制服务(无 tmux 依赖)。\n- overlay 端口桥:EXPOSE(<overlayIP>:<port> → 本机服务,带来源 overlay\n  前缀白名单)与 FORWARD(127.0.0.1:<port> → 远端 overlay 服务)。\n- 控制面代理可关(SetControlProxyEnabled):纯组网节点不暴露 7699 代理。\n- kernel tun 支持与 svc 安装适配。\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(mesh): ccfly-mesh 最小组网客户端 + overlay 端口桥 + kernel tun",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-13T01:01:42Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d73a19fafacae479034a061ab846c664ad3d01df",
          "body": "- ccfly ls [-a]:以目录为核心的会话总览——按 cwd 分组、组内最近活动倒序,\n  每行给出可直接复制执行的接管命令(live → tmux a -t <真 pane 名>,离线 →\n  ccfly attach <sid8>);默认每目录 5 条,live 恒全展示。\n- ccfly a / attach:无参进入两级 TUI(选项目 → 选会话 → Enter 接管),\n  纯 ANSI + raw mode(x/term),备用屏进出;带参直连。live → attach 镜像;\n  离线 → takeover 杀残留进程后 tmux 里 claude --resume(防双写唯一入口)。\n- ccfly new [dir]:新 tmux 会话起全新 claude。\n- ccfly panemap-hook:SessionStart hook 入口(最先短路,不付登录壳探测开销)。\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(cli): ccfly ls / a(交互式选择器)/ attach / new",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-13T01:01:29Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "f2fc99a7a427b34b95ef42313e250da92344df89",
          "body": "- GET /sse/jsonl:把会话 jsonl 以原始行 + 字节 offset 推给表世界(fsnotify\n  驱动,id=offset 断线续传);跟随 pane 锚,/clear 换文件发 switched。\n- follow 愈合:客户端带 Last-Event-ID / ?follow=1 重连且请求的 sid 已死时,\n  经真值表 prev 轨迹锚回原 pane、直接续其当前会话——断线窗口里错过的\n  /clear 在重连时跟上;主动浏览历史(无 follow)仍静态渲染绝不跳走。\n- GET /jsonl/before:向上翻页(headStart 之前一窗更老原始行)。\n- POST /takeover:确定性杀掉会话既有 claude 进程(防双写),供 attach/web\n  重建进 tmux。\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(control): /sse/jsonl 原始事件流(follow 愈合 + 分页)与 takeover",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-13T01:01:29Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "44a98318331f2807863f33217ddd9f6db96b6552",
          "body": "根治「webui 消息错发到别的会话」:pane 里跑着的 sid 会被 /clear、里世界\n/resume 换掉,而 tmux 名永不变;同 cwd 多 pane 时旧的 cwd+最近活动启发式\n取 list 第一个 = 抽奖错发。现在:\n\n- SessionStart hook(ccfly panemap-hook)在每次会话开始时把「pane → 当前\n  sid」写进 ~/.ccfly/panemap.json 真值表;安装幂等且自愈(临时实例劫持\n  hook 路径、其二进制被删后,巡检 ≤1 拍修复——实案教训)。\n- 解析分层:真值表(确定性)→ 精确同名 → fail-clo\n[…]\nsessions 的 rows 按「客户端视口」报(窗口 + tmux 状态栏行数),否则\n  web 隐藏终端矮一行裁掉 idle footer,读屏检测全灭(卡死「生成中」实案)。\n- 扫描缓存(mtime+size 逐文件 + 短整轮 memo)与后台巡检(cc-* 孤儿壳回收)。\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(control): pane↔sid 真值表(panemap)与会话解析全面加固",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-13T01:01:10Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c783ca83cd86767dc72fe8949cca7a38623a6e3f",
          "body": "Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: gitignore .claude/",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-13T01:01:10Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "c3e4244bf2fb8d057a504c5fc48c7ae5bca67d1d",
          "body": "Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release: ccfly 0.4.10, @ccfly/react 0.4.4",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-08T05:17:29Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "4ae8025230fd7eae373f58bdd77b033e7e0e33d1",
          "body": "Device (control.go): waited zero time after the last bracketed image\npaste before Enter, so Enter landed in Claude Code's async paste-ingest\nwindow and was swallowed — text + [Image #N] sat unsent. Now poll\ncapture-pane for the [Image #N] placeholders (baseline-delta, ~1.4s\ntimeout fallback) before \n[…]\n.is-pressed), visible+tappable not-ready state (.is-off) that flashes\nthe reason, and long-press with image-only now sends instead of dropping.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: image submit reliability (device Enter race + compose send-button)",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-08T05:16:22Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "af2e74f7c92316f3d497914d462b8332142f36d0",
          "body": "附图改走终端「拖拽文件」的底层机制:tmux set-buffer + paste-buffer -p(括号粘贴)把上传图\n的绝对路径粘进里世界输入框,Claude 原生嵌成 [Image #N]。纯 tmux 往 PTY 注字节、与 GUI/剪贴板\n无关 → --system / headless 一样能用,不再需要 0.4.8 的 CCFLY_IMAGE_PATHS 特判,移除 darwin\nosascript 剪贴板通道(及 imgClip/pngfClassForExt/appleScriptQuote)。\n\n实测(v2.1.168):文本 + 多图 → [Image #1] [Image #2] 原生嵌入、序号正确、buffer 不残留(-d),\nClaude 正确读出两张。优雅降级:某版 Claude 不再自动嵌图时路径落框 → Claude 仍 Read 取图。\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(image): 括号粘贴路径原生附图,全平台统一(含 --system);release ccfly 0.4.9",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-08T03:19:18Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "4ddeabfa07306b6af800b12e7e72dd7ca9e148fe",
          "body": "--system(LaunchDaemon)跑在系统上下文、拿不到 GUI 登录会话的剪贴板:osascript 写的剪贴板\n与里世界 Claude(tmux 里)读的不是同一块,launchctl asuser 也注入不进 → 截图粘不进消息。\n改为安装 --system 时在 plist 注入 CCFLY_IMAGE_PATHS=1,控制服务据此走与 Linux 相同的回退:\n把图片绝对路径拼进输入框文本,Claude 用 Read 工具读图(上传落在会话 cwd 内的 .ccfly-uploads/,\nRead 默认放行、不弹权限,实测可正确读出图片内容)。用户级安装无此 env、仍走剪贴板原生粘贴\n(干净的 [Image #N])。移除上一版失败的 launchctl asuser 尝试。\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(image): --system 改走「路径拼文本」回退,绕开它没有的 GUI 剪贴板;release ccfly 0.4.8",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-08T02:53:40Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "ca46bfc19d82612ec39d2f5eb29cc31c5f5ffa95",
          "body": "Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release: ccfly 0.4.7 — image paste under --system via launchctl asuser",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-08T02:13:22Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "8a0c8042a0f8bf187c9c133827c91c9242083a03",
          "body": "Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release: ccfly 0.4.6 — stable machine-id pairing dedup",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-07T18:36:40Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "32ca6045e0f98978707ffb9f251c2d3900d0b18a",
          "body": "ccfly install accepts flags in any position; prompts for host (default\ncc.hn) when omitted instead of erroring on a leading --system.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release: ccfly 0.4.5 — install flag-order + interactive host",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-07T18:11:33Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "bf65aa0fa745069e4354bab6c1b2335b5455144c",
          "body": "Screen-state engine + all rich selects ported; cc.hn Hub & Node branding.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release: ccfly 0.4.4 · @ccfly/react 0.4.3",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-07T17:56:06Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "97421e2f301d99b6c7fed2916dd41f5399217c46",
          "body": "permission / effort / confirm / multi / sessionScope / list — each a\nState<Info> subclass + View in one self-registering file, on the new\nattribute-aware engine. Shared pre gains title + options[].checked.\nCentral states/index dispatches kind->View (EngineControl); ControlBar's\nselect branch now defers to the engine live, old cards kept only as the\nWS-degraded fallback.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(react): port remaining rich selects to the screen-state engine",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-07T17:03:57Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "601a81a22093b43b6d5f3cd68550ea3b5fbec291",
          "body": "New read-screen pipeline in @ccfly/react: attribute-aware Frame (cur from\ninverse/bg highlight, not just ❯ glyph — fixes glyphless /model picker),\none-time pre features, decentralized State registry by weight, and\nclosed-loop command primitives (send + waitFor). modelSelect is the first\nstate on it:\n[…]\n refactoring the remaining rich selects. Rollback: `git\ncheckout main` (pre-engine) or reset to this commit (working modelSelect).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(react): screen-state engine + modelSelect on it (checkpoint)",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-07T16:46:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5997952800b8978efdb4fb30505da9f68ad11153",
          "body": "Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release: ccfly 0.4.3 (no-code device pairing CLI)",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-07T13:14:04Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "cbaf8847fb56ff891df0e3de9a643adca9b2e223",
          "body": "… approve → bind\n\nDevice CLI: when the connect/install target has no /<code>, run a device-authorization flow — POST /api/pair/start, print + auto-open the approval link, poll (Authorization: Bearer pollToken) until approved, then enroll from the returned creds and hold the tunnel. Saved-state reconnect skips re-pairing (installed service runs plain 'connect <host>'). The <host>/<code> flow is unchanged.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(pair): no-code device pairing — 'ccfly install <host>' → browser…",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-07T13:08:53Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "6ecbd553c636021b92389af01769aab4e6640ee2",
          "body": "…/false-positive fixes)\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release: ccfly + @ccfly/react 0.4.2 (native image embed + busy de-dup…",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-07T11:20:34Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "51a0bb3aea6a3f4a3c440f4fe4b4a65aeddf6b5d",
          "body": "- AgentDock no longer renders a main-busy row (duplicated ControlBar BusyLine); it now shows only running subagents/workflows. BusyLine is the single main-busy source.\n- detectState (ctrlstate.go + livestate.ts, lockstep): a clear numbered select pre-empts busy — Claude Code keeps the 'esc to interr\n[…]\nents stop showing as 'running' (a busy misreport in AgentDock).\n- tests: F8/F9 (select-vs-busy footer) + terminal-status coverage.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(busy): de-dup busy panel (drop AgentDock main row) + stop false busy",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-07T08:30:26Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "66cd3c441dd2bbb1d972c566545f51725e616368",
          "body": "…ile paths\n\nReal Claude Code image messages are base64 image blocks ([Image #N]), never paths. So instead of appending the uploaded path to the message text, the device now sets the image on the system clipboard and sends C-v to the session — Claude Code embeds [Image #N] natively. /sendkeys gains a\n[…]\n+ exec args, no shell; reuses upload.go containment); non-darwin falls back to appending paths. Mechanism verified live on-device.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(upload): embed images natively via clipboard+Ctrl+V paste, not f…",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-07T08:14:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "43728042d0f2d7b162f437077af5a7f4d97b7649",
          "body": "Device sends its build version in the /connect enroll body; cloud stores it on the Device record and the web shows it, so 'did this device pick up the new build?' is visible at a glance.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(mesh): device reports client version on enroll; release ccfly 0.4.1",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-07T07:23:24Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "13a83349862bb06cbe4e15a1ee2a6e176ec0cfc3",
          "body": "…/react 0.4.1\n\nBare '\\n' in the submit payload is typed literally via tmux send-keys -l, where it = Enter = submit — so 'text<newline>path' submitted on the text alone and the path lines orphaned (uploaded image never reached the message). Join text + device paths with a space (paths are UUID filenames, no spaces) so it's one line, no premature submit.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(react): merge uploaded paths with space, not newline; bump @ccfly…",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-07T07:23:24Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "b866847b71a13a1c1523200057485cb8fc861c25",
          "body": "…clear tmux resolve, /compact percent)\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release: ccfly 0.4.0 (device binary — upload handler, server floor, /…",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-07T06:18:26Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "0ca7173fd9c257e30697dc93a471afc6d4ce85b6",
          "body": "…ST /upload; add @ccfly/react package README\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: README — rich selects, image/file upload, /compact progress, PO…",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-07T05:53:18Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "bfc0b06e7a45cd144381bd46446fe81580d55fb7",
          "body": "…/clear tmux resolve, file upload\n\n- control.go: /sendkeys 'clear' flag -> C-a C-k clear primitive + server floor (re-capture + detectState, 409 when kind != input); POST /upload route\n- upload.go (new): hardened multipart upload — MaxBytesReader (env cap) before parse, server-generated UUID name, s\n[…]\nux by cwd+recency (fixes /clear rebinding); wired into sessions/term/control\n- sessions.go / term.go: session-resolution touch-ups\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(control): guarded-atomic-submit server floor, /compact percent, …",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-07T05:16:13Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0f6391168b94e514fb13d8527132548f4b39bad8",
          "body": "…& workflow cards\n\n- select/: Rich{Model,Permission,Effort,Confirm,SessionScope,Multi,List}Select + selectKind classifier\n- AttachmentBar: image/file upload (paste/picker/drag-drop), upload-on-add, thumbnails, predict hint\n- ControlBar: guarded atomic submit funnel (clear + certain gate + 409 re-syn\n[…]\nkingBlock TUI style\n- api/sendkeys: SendResult {ok,kind}; clear flag; uploadFile (XHR progress)\n- bump @ccfly/react 0.3.3 -> 0.4.0\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(react): rich selects, file upload, compose redesign, compaction …",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-07T05:16:00Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "cac34a61d86a862ec37f198ee9b87e69c525445e",
          "body": "Ships the recent web-UI work into the device's embedded SPA + npm:\n- /cost panel sweep-all-tabs (instant tab switching)\n- /context as a jsonl-notification card\n- AgentDock /subagents polling gated by live state (no idle polling)\n- livestate shellEvidence fix (no offline misclassification)\n- LiveTerm frozen-mirror watchdog (busy stuck-state recovery)\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release: ccfly 0.3.10 · @ccfly/react 0.3.3",
          "author_name": "Jin",
          "author_login": "jsdvjx",
          "committed_at": "2026-06-06T15:51:33Z",
          "body_truncated": false,
          "is_coding_agent": true
        }
      ],
      "releases_count": 3,
      "commits_last_year": 129,
      "latest_release_at": "2026-06-06T15:51:33Z",
      "latest_release_tag": "v0.3.10",
      "releases_from_tags": true,
      "days_since_last_push": 5,
      "active_weeks_last_year": 8,
      "days_since_latest_release": 48,
      "mean_days_between_releases": 0.1
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": false,
      "health_percentage": 42,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "github.com/jsdvjx/ccfly",
          "exists": true,
          "license": null,
          "keywords": [],
          "ecosystem": "go",
          "matches_repo": true,
          "registry_url": "https://pkg.go.dev/github.com/jsdvjx/ccfly",
          "is_deprecated": false,
          "latest_version": "v0.3.10",
          "repository_url": "https://github.com/jsdvjx/ccfly",
          "versions_count": 3,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": null,
          "latest_published_at": "2026-06-06T15:51:33Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 48
        }
      ]
    },
    "popularity": {
      "forks": 0,
      "stars": 1,
      "watchers": 0,
      "fork_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_forks": 0
      },
      "star_history": null,
      "open_issues_and_prs": 0
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [
        "examples"
      ],
      "has_llms_txt": false,
      "has_dockerfile": true,
      "has_mcp_signal": false,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [
        "examples/web/tsconfig.json",
        "packages/react/tsconfig.json"
      ],
      "toolchain_manifests": [
        "go/go.mod"
      ],
      "largest_source_bytes": 51187,
      "source_files_sampled": 226,
      "oversized_source_files": 0,
      "agent_instruction_files": [
        "CLAUDE.md"
      ],
      "agent_instruction_max_bytes": 10363
    },
    "dependencies": {
      "manifests": [
        "go/go.mod",
        "package.json"
      ],
      "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",
        "npm"
      ],
      "dependencies": [
        {
          "name": "github.com/UserExistsError/conpty",
          "manifest": "go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.1.4"
        },
        {
          "name": "github.com/coder/websocket",
          "manifest": "go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.8.14"
        },
        {
          "name": "github.com/coredns/caddy",
          "manifest": "go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.1.4-0.20250930002214-15135a999495"
        },
        {
          "name": "github.com/coredns/coredns",
          "manifest": "go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.14.6"
        },
        {
          "name": "github.com/creack/pty",
          "manifest": "go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.1.24"
        },
        {
          "name": "github.com/fsnotify/fsnotify",
          "manifest": "go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.10.1"
        },
        {
          "name": "github.com/miekg/dns",
          "manifest": "go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.1.72"
        },
        {
          "name": "golang.org/x/crypto",
          "manifest": "go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.53.0"
        },
        {
          "name": "golang.org/x/sys",
          "manifest": "go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.47.0"
        },
        {
          "name": "golang.org/x/term",
          "manifest": "go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.44.0"
        },
        {
          "name": "golang.zx2c4.com/wireguard",
          "manifest": "go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.0.0-20260522210424-ecfc5a8d5446"
        }
      ],
      "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": 0,
        "open_issues": 0,
        "closed_ratio": null,
        "closed_issues": 0,
        "closed_unmerged_prs": 0
      },
      "bus_factor": 1,
      "bot_contributors": 0,
      "top_contributors": [
        {
          "type": "User",
          "login": "jsdvjx",
          "commits": 129,
          "avatar_url": "https://avatars.githubusercontent.com/u/12291665?v=4"
        }
      ],
      "contributors_sampled": 1,
      "top_contributor_share": 1
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "ci.yml",
        "release.yml"
      ],
      "has_docs_dir": false,
      "linter_configs": [],
      "has_editorconfig": false,
      "has_linter_config": false,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [
        "go.sum",
        "pnpm-lock.yaml"
      ],
      "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": null,
            "reason": "no pull request found",
            "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/30 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 0,
            "reason": "project has 0 contributing companies or organizations -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": 10,
            "reason": "no dangerous workflow patterns detected",
            "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": 0,
            "reason": "project was created within the last 90 days. Please review its contents carefully",
            "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": 0,
            "reason": "dependency not pinned by hash detected -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "no SAST tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 0,
            "reason": "security policy file not 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": 0,
            "reason": "detected GitHub workflow tokens with excessive permissions",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 3,
            "reason": "7 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "a4ba628519d56bdcb35911778eaa7a38b43d67cd",
        "ran_at": "2026-07-25T12:41:21Z",
        "aggregate_score": 2.5,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": false,
      "has_dependabot_config": false
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-20T11:37:44Z",
      "oldest_open_prs": [],
      "last_merged_pr_at": null,
      "ci_last_conclusion": "FAILURE",
      "oldest_open_issues": []
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/jsdvjx/ccfly",
    "host": "github.com",
    "name": "ccfly",
    "owner": "jsdvjx"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "at_risk",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 43,
      "inputs": {
        "security": 25,
        "vitality": 71,
        "community": 24,
        "governance": 31,
        "engineering": 56
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "good",
        "name": "Vitality",
        "value": 71,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "moderate",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 60,
            "inputs": {
              "commits_last_year": 129,
              "human_commit_share": 1,
              "days_since_last_push": 5,
              "active_weeks_last_year": 8
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 5 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 5
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "8/52 weeks with commits",
                "points": 5.5,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 8
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "129 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 129
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "project was created within the last 90 days. Please review its contents carefully",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "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": 88,
            "inputs": {
              "releases_count": 3,
              "latest_release_tag": "v0.3.10",
              "releases_from_tags": true,
              "days_since_latest_release": 48,
              "mean_days_between_releases": 0.1
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "3 version tags (no GitHub releases)",
                "points": 16.2,
                "status": "partial",
                "details": [
                  {
                    "code": "version_tags_no_releases",
                    "params": {
                      "count": 3
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 48 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 48
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~0.1 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 0.1
                    }
                  }
                ],
                "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": 31,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 10,
            "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 0 contributing companies or organizations -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "critical",
            "name": "Issue & PR responsiveness",
            "note": "Excluded from scoring (no data or not applicable): Issue resolution, PR acceptance. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "issue_resolution",
                    "pr_acceptance"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 1,
            "inputs": {
              "merged_prs": 0,
              "open_issues": 0,
              "closed_issues": 0,
              "issue_closed_ratio": null,
              "closed_unmerged_prs": 0
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "no issues or no data",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_issues_or_data",
                    "params": {}
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "no decided pull requests or no data",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_decided_prs_or_data",
                    "params": {}
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "at_risk",
            "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": 37,
            "inputs": {
              "followers": 1,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "jsdvjx",
              "public_repos": 5,
              "account_age_days": 4097
            },
            "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": "1 followers of jsdvjx",
                "points": 2.2,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 1,
                      "login": "jsdvjx"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "5 public repos, account ~11 yr old",
                "points": 17.7,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 5
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 11
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 92,
            "inputs": {
              "packages": [
                "github.com/jsdvjx/ccfly"
              ],
              "ecosystems": "go",
              "any_deprecated": false,
              "min_days_since_publish": 48
            },
            "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 48 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 48
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "3 published versions",
                "points": 12,
                "status": "partial",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 3
                    }
                  }
                ],
                "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": "moderate",
        "name": "Engineering Quality",
        "value": 56,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "moderate",
            "name": "Engineering practices",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: CI-Tests. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_ci_tests"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 60,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "2 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "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": "no pull request found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "moderate",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 50,
            "inputs": {
              "topics": [],
              "has_wiki": true,
              "homepage": null,
              "has_readme": true,
              "has_docs_dir": false,
              "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": 0,
                "status": "missed",
                "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": 25,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "critical",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): CI-Tests, Packaging, Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "ci_tests",
                    "packaging",
                    "signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 25,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 15,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 3,
              "scorecard_aggregate": 2.5
            },
            "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": "no pull request found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "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/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 0 contributing companies or organizations -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no dangerous workflow patterns detected",
                "points": 10,
                "status": "met",
                "details": [],
                "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": "project was created within the last 90 days. Please review its contents carefully",
                "points": 0,
                "status": "missed",
                "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": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "no SAST tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file not detected",
                "points": 0,
                "status": "missed",
                "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": "detected GitHub workflow tokens with excessive permissions",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "7 existing vulnerabilities detected",
                "points": 2.2,
                "status": "partial",
                "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": "good",
        "name": "AI Readiness",
        "value": 73,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "excellent",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 85,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.98,
              "agent_instruction_files": [
                "CLAUDE.md"
              ],
              "agent_instruction_max_bytes": 10363
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "CLAUDE.md",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "CLAUDE.md"
                    }
                  }
                ],
                "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": "98 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 98,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "moderate",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 66,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "go.sum",
                "pnpm-lock.yaml"
              ],
              "has_dockerfile": true,
              "typed_language": true,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [
                "examples/web/tsconfig.json",
                "packages/react/tsconfig.json"
              ],
              "agent_commit_share": 0.8,
              "toolchain_manifests": [
                "go/go.mod"
              ],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": "go/go.mod (toolchain convention, no task runner)",
                "points": 12.6,
                "status": "partial",
                "details": [
                  {
                    "code": "toolchain_convention",
                    "params": {
                      "files": "go/go.mod"
                    }
                  }
                ],
                "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": "examples/web/tsconfig.json, packages/react/tsconfig.json",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "examples/web/tsconfig.json, packages/react/tsconfig.json"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": "Dockerfile, lockfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "Dockerfile, lockfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "80 of the last 100 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 80,
                      "sampled": 100
                    }
                  }
                ],
                "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": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "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": 51187,
              "source_files_sampled": 226,
              "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/226 source files over 60KB",
                "points": 55,
                "status": "met",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 226,
                      "oversized": 0
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          },
          {
            "key": "ai_interfaces",
            "band": "at_risk",
            "name": "Machine-readable interfaces",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "example_dirs": [
                "examples"
              ],
              "has_mcp_signal": false,
              "api_schema_files": []
            },
            "components": [
              {
                "key": "api_schema_openapi_graphql_proto",
                "name": "API schema (OpenAPI/GraphQL/proto)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 40
              },
              {
                "key": "mcp_server",
                "name": "MCP server",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "runnable_examples",
                "name": "Runnable examples",
                "detail": "examples",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "examples"
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          }
        ],
        "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-25T12:41:26.636570Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/j/jsdvjx/ccfly.svg",
  "full_name": "jsdvjx/ccfly",
  "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.