Public record
Software health reportschema 0.27.0 · metrics 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 star⑂ 0 forkssince Jun 2026View on GitHub ↗

jsdvjx/ccfly holds a health index of 43 out of 100, placing it in the At risk band. It scores highest on AI Readiness (73/100) and lowest on Community & Adoption (24/100). It was last updated 5 days ago. A single contributor accounts for most of its recent work.

43
overall / 100
At risk

Software health index

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

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

Score profile

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

Ownership

jsdvjxPersonal account
1 follower5 public repossince May 2015

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

Package ecosystems

RegistryPackageVersionDownloads / moVersionsLast publish
Gogithub.com/jsdvjx/ccflyv0.3.10-348 days ago

Metrics by category

Vitality

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

71Good · 22% of overall
How it's scored
36/36Push recency — last push 5 days ago
5.5/36Commit cadence — 8/52 weeks with commits
18/18Commit volume — 129 commits in the last year
0/10OpenSSF Scorecard: Maintained — project was created within the last 90 days. Please review its contents carefully
Inputs used
commits_last_year129
human_commit_share1
days_since_last_push5
active_weeks_last_year8
How it's scored
16.2/27Ships releases — 3 version tags (no GitHub releases)
36/36Release recency — latest release 48 days ago
27/27Release cadence — a release every ~0.1 days
0/10OpenSSF Scorecard: Signed-Releases — no data
Inputs used
releases_count3
latest_release_tagv0.3.10
releases_from_tagsyes
days_since_latest_release48
mean_days_between_releases0.1
Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.

Community & Adoption

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

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

Sustainability & Governance

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

31At risk · 24% of overall
How it's scored
9/54Bus factor — 1 contributor(s) cover half of all commits
0/22.5Commit distribution — top contributor authored 100% of commits
1.4/13.5Contributor breadth — 1 contributors
0/10OpenSSF Scorecard: Contributors — project has 0 contributing companies or organizations -- score normalized to 0
Inputs used
bus_factor1
contributors_sampled1
top_contributor_share1
How it's scored
0/46.8Issue resolution — no issues or no data
0/38.3PR acceptance — no decided pull requests or no data
0/15OpenSSF Scorecard: Code-Review — Found 0/30 approved changesets -- score normalized to 0
Inputs used
merged_prs0
open_issues0
closed_issues0
issue_closed_ratio
closed_unmerged_prs0
Excluded from scoring (no data or not applicable): Issue resolution, PR acceptance. Remaining weights renormalized.
How it's scored
10/30Ownership backing — personal (user) account
0/20Verified domain — not applicable to user accounts
2.2/25Owner reach — 1 followers of jsdvjx
17.7/25Track record — 5 public repos, account ~11 yr old
Inputs used
followers1
owner_typeUser
is_verified
owner_loginjsdvjx
public_repos5
account_age_days4,097
Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.
How it's scored
25/25Published & resolvable — 1 package(s) on go
35/35Publish recency — latest publish 48 days ago
12/20Version history — 3 published versions
20/20Not deprecated — active, not deprecated or yanked
Inputs used
packagesgithub.com/jsdvjx/ccfly
ecosystemsgo
any_deprecatedno
min_days_since_publish48

Engineering Quality

Are baseline engineering and documentation practices in place?

56Moderate · 20% of overall
How it's scored
24/24CI workflows — 2 workflow(s)
24/24Tests present
0/16Linter config
0/9.6Pre-commit hooks
0/6.4.editorconfig
0/20OpenSSF Scorecard: CI-Tests — no data
Inputs used
has_ciyes
has_testsyes
has_editorconfigno
has_linter_configno
has_precommit_configno
Excluded from scoring (no data or not applicable): OpenSSF Scorecard: CI-Tests. Remaining weights renormalized.

Documentation

50Moderate
How it's scored
30/30README
0/25Documentation directory
0/15Documentation / homepage site
10/10Repository description
0/10Topics
10/10Wiki
Inputs used
topics
has_wikiyes
homepage
has_readmeyes
has_docs_dirno
has_descriptionyes

Security

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

25Critical · 16% of overall
How it's scored
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — branch protection not enabled on development/release branches
0/2.5CI-Tests — no data
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.5License — license file detected
0/7.5Maintained — project was created within the last 90 days. Please review its contents carefully
0/5Packaging — no data
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 — no data
0/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
2.2/7.5Vulnerabilities — 7 existing vulnerabilities detected
Inputs used
sourceopenssf_scorecard
checks_evaluated15
scorecard_versionv5.5.0
checks_inconclusive3
scorecard_aggregate2.5
Excluded from scoring (no data or not applicable): ci_tests, packaging, signed_releases. Remaining weights renormalized.

AI Readiness

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

73Good · 0% of overall
How it's scored
45/45Agent instructions — CLAUDE.md
0/15Machine-readable docs (llms.txt)
40/40Legible commit history — 98 of 100 human commits state their intent (structured subject or explanatory body)
Inputs used
has_llms_txtno
legible_history_share0.98
agent_instruction_filesCLAUDE.md
agent_instruction_max_bytes10,363
How it's scored
12.6/18One-command bootstrap — go/go.mod (toolchain convention, no task runner)
22/22Automated tests
0/11Lint / format config
11/11Static type checking — examples/web/tsconfig.json, packages/react/tsconfig.json
10/10Reproducible environment — Dockerfile, lockfile
10/10Demonstrated agent practice — 80 of the last 100 commits agent-authored or agent-credited
0/8Automated maintenance — no automated dependency updates observed
0/10OpenSSF Scorecard: Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
Inputs used
has_nixno
has_testsyes
lockfilesgo.sum, pnpm-lock.yaml
has_dockerfileyes
typed_languageyes
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
How it's scored
45/45Type-checkable code — Go (statically typed)
55/55Manageable file sizes — 0/226 source files over 60KB
Inputs used
primary_languageGo
largest_source_bytes51,187
source_files_sampled226
oversized_source_files0
How it's scored
0/40API schema (OpenAPI/GraphQL/proto)
0/20MCP server
40/40Runnable examples — examples
Inputs used
example_dirsexamples
has_mcp_signalno
api_schema_files

Key facts

1GitHub stars
1contributors
129commits, last 12 months
5days since last push
3releases
1bus factor
0open issues
Go, npmpackage ecosystems

Data collection warnings

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

More detail

OpenSSF Scorecard 2.5 / 10
2.5aggregate

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

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
n/aCI-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/aPackagingpackaging 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/aSigned-Releasesno releases found
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
3Vulnerabilities7 existing vulnerabilities detected
Direct dependencies 11
RegistryPackageVersion constraintManifest
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
All dependencies not collected

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

Raw JSON report machine-readable
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 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"
}

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

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

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