codeburn sync 技术全解:从 OIDC/PKCE 认证到 OTLP 遥测推送的本地优先架构
2026/9/24 7:03:04 网站建设 项目流程

【免费下载链接】codeburn

Free, local tool to track AI coding token usage and cost across 37 tools and agents (Claude Code, Cursor, Codex, Gemini and more), by model, project, and task. npx codeburn

项目地址:https://gitcode.com/gh_mirrors/co/codeburn
点击查看免费下载

本文是codeburn同步子系统(codeburn sync)的开发者级技术指南,以仓库 docs/sync/DEVELOPER.md 为骨架,结合 src/sync/ 下的源码实现展开。你将掌握:服务端发现协议(codeburn-export.json)、Authorization Code + PKCE 认证与令牌刷新、跨平台凭据存储、确定性 OTLP span 编码、基于 sent-ledger 的精确去重与限流回退,以及从纯函数单元测试到真实 Cognito 的无头浏览器 e2e 测试策略。

codeburn是一款本地优先的 AI 编码用量追踪工具,codeburn sync是其可选的团队级能力:把本地解析出的 AI 使用遥测(token、成本、项目、工具)推送到团队自建的后端,用于追踪采纳率、预算与 ROI。与codeburn的整体理念一致,同步默认不发送任何数据——必须显式执行codeburn sync push,且提示词与代码永远不会出现在载荷中。本文面向希望接入、自建后端或深度理解该子系统的开发者。

架构总览:一次sync push的完整旅程

codeburn sync的架构可以用一张数据流图概括(来自 docs/sync/DEVELOPER.md):

Developer machine Remote backend ────────────────── ────────────── ~/.config/codeburn/sync.json (config) ~/.config/codeburn/.sync-token (credential) ~/.cache/codeburn/sync-ledger.json (sent-ledger) codeburn sync push │ ├─ Read config → baseUrl, clientId, issuer, tracesPath ├─ Read refresh token from OS store ├─ POST {issuer}/oauth2/token (refresh_token grant) → access_token ├─ Collect ParsedProviderCall[] for window ├─ Filter against sent-ledger (only unsent calls) ├─ Build OTLP/HTTP JSON payload ├─ POST {baseUrl}{tracesPath} with Bearer token ├─ On success → append deduplicationKeys to ledger └─ Update lastSync in config

这条链路在源码中被拆分为职责单一的可测试模块,全部位于 src/sync/:

模块职责
discovery.ts拉取并校验服务端发现文档
auth.tsOIDC 发现、PKCE 生成、回调服务器、令牌交换/刷新/撤销
credentials.ts跨平台凭据存取(keychain / secret-tool / DPAPI / 文件回退)
config.tssync.json非敏感配置的读写
ledger.tssent-ledger 已发送去重账本的读写与剪枝
otlp.tsParsedApiCall → OTLP/HTTP JSON 载荷构建
push.ts收集/过滤/分批/发送/记账的推送编排
cli.tssync setup / push / status / logout / reset五个子命令

这种拆分的一个直接收益在 push.ts 的注释中写明:flatten/filter/batch/send/ledger 管线被提取出来,无需完整 CLI 调用即可单元测试。

服务端发现协议:codeburn-export.json

codeburn sync setup <url>的第一步,是从远端拉取服务发现文档,而不是直接猜测后端接口。协议定义如下:

GET {baseUrl}/.well-known/codeburn-export.json

返回的 JSON 示例与字段契约(继承自 docs/sync/DEVELOPER.md):

{ "version": 1, "issuer": "https://cognito-idp.us-west-2.amazonaws.com/us-west-2_XXXX", "client_id": "70e6sgst2ju6ff9dnrmv4l1tcb", "scopes": ["openid", "email"], "traces_path": "/v1/traces", "max_batch_size": 1000 }
字段是否必填默认值说明
version1客户端拒绝version > 1的端点
issuerOIDC issuer URL,客户端随后获取{issuer}/.well-known/openid-configuration
client_id本次部署的 OAuth client ID
scopes["openid"]请求的 scope;若 IdP 支持,offline_access会被动态追加
traces_path/v1/tracesOTLP POST 的目标路径
max_batch_size1000每次 HTTP 请求的最大 span 数

源码解析器 discovery.ts 严格实现了这份契约:version缺省视为1、超出则抛错提示升级;issuerclient_id缺失直接拒绝;scopes非字符串元素会被过滤;traces_pathmax_batch_size分别回退到/v1/traces1000。解析前还会调用assertHttps强制远端端点必须为 HTTPS——该函数只放行https:与环回地址(127.0.0.1[::1]localhost)的明文http:,理由是刷新令牌与 Bearer 令牌都会经由这些 URL 传输。

为什么不直接代理.well-known/openid-configuration

OIDC 规范要求发现文档中的issuer声明必须与其被获取的 URL 一致(issuer mix-up 防御)。如果从一个非 Cognito 域名代理 Cognito 的发现文档,就会违反这一约束。codeburn-export.json的设计价值在于:把指标端点(metrics endpoint)与身份提供方(identity provider)解耦。服务端可以任意选择 IdP,客户端只需从这一份自定义发现文档中拿到issuer再走标准 OIDC 流程。

值得补充的是,客户端在获取 OIDC 配置时同样执行 issuer 一致性校验——auth.ts 中,如果 OIDC 元数据的issuer声明与实际请求的 issuer 不符,会直接抛出AuthError拒绝握手。

OIDC 认证:Authorization Code + PKCE

同步使用标准 OIDC(与 "Sign in with Google" 相同的协议)。团队管理员配置好 IdP,开发者只需在首次sync setup时通过浏览器点一次登录。

完整认证流程

docs/sync/DEVELOPER.md 中给出了七步流程,结合 auth.ts 的实现可以完整还原:

  1. 生成 PKCE 挑战:客户端生成code_verifier(32 字节随机数,base64url 编码)与code_challenge(对 verifier 做 SHA-256 后 base64url)。对应实现 generatePkce。
  2. 启动回调服务器:监听127.0.0.1:19876(回退 19877、19878)。对应 startCallbackServer。
  3. 打开浏览器:访问{authorization_endpoint}?response_type=code&client_id=...&redirect_uri=http://127.0.0.1:{port}/callback&code_challenge=...&code_challenge_method=S256&state=...&scope=...。对应 buildAuthUrl。
  4. 用户在 IdP 登录,IdP 重定向到http://127.0.0.1:{port}/callback?code=...&state=...
  5. 回调服务器校验state,提取code。回调处理中state不匹配返回 400 且不关闭服务器(可能只是过期请求);IdP 返回error参数则直接终止;5 分钟无回调则超时失败。
  6. 客户端 POST 令牌端点grant_type=authorization_codecodecode_verifierredirect_uriclient_id。对应 exchangeCode。
  7. IdP 返回access_token+refresh_token

固定端口的意义

Cognito(以及 Okta)对回调 URL 做精确字符串比较,临时端口(ephemeral port)无法通过校验。因此客户端注册了三个固定端口198761987719878(定义于 auth.ts),按顺序尝试,端口被占用则回退下一个。源码中的tryListen循环对EADDRINUSE逐个尝试,且用resolvedPort守卫避免 late error 事件触发二次listen;cli.ts 会先await ready拿到实际绑定成功的端口再构造 redirect URI(因为端口回退意味着第一个端口不保证可用)。

另外,RFC 8252 建议回调地址使用127.0.0.1(IP 字面量)而非localhost,以避免 IPv6::1解析问题——这正是本项目固定使用 IP 字面量的原因。

令牌刷新与失效处理

每次sync push时:

  1. 从 OS 凭据存储读取 refresh token;
  2. POST{token_endpoint}grant_type=refresh_token(实现见 refreshToken);
  3. 无论服务器返回什么 refresh token 都直接存储——透明地处理令牌轮换(rotation);
  4. 遇到invalid_grant(HTTP 400/401)→ 停止,提示用户重新运行codeburn sync setup

Scope 解析

  • 基础 scope 来自codeburn-export.jsonscopes字段;
  • 仅当 OIDC 发现的scopes_supported中包含offline_access时才追加该 scope(实现见 resolveScopes);
  • 特别地,Cognito 会以invalid_scope拒绝offline_access——但它无需该 scope 也会签发 refresh token,所以这里按 IdP 能力动态处理是必须的。

凭据存储:OS 原生安全存储 + 文件回退

refresh token 属于长期凭据,必须放进系统级安全存储。credentials.ts 按平台选择实现(createCredentialStore):

平台方法实现
macOSKeychainsecurity add-generic-password/find-generic-password
Linuxlibsecretsecret-tool store/secret-tool lookup
WindowsDPAPIPowerShellConvertTo-SecureString/ConvertFrom-SecureString
回退文件~/.config/codeburn/.sync-token,权限0600

项目刻意不引入原生模块keytar已归档停止维护),而是 shell out 到操作系统自带的 CLI。几个实现细节值得注意:

  • macOS 路径通过execFileSync传参而非 shell 拼接,避免注入;注释坦言令牌仍会短暂出现在进程参数中(security无非交互 stdin 模式,这是当前能做到的最好方案)。
  • Linux 路径将令牌经stdin传给secret-tool,绝不落入 argv;创建 store 前还会用一个探针 key 探测 keyring 守护进程是否在运行——只有探测通过(或确认 keyring 正常工作)才使用 secret-tool,否则回退文件存储。
  • Windows 路径经环境变量把令牌传给 PowerShell,再用 DPAPI 加密后落盘为.sync-token-dpapi,同样0600
  • 文件回退路径写入后还会显式chmodSync(0o600),因为writeFile的 mode 对已存在文件不一定生效。

sync status如实报告当前使用的是 keychain 还是文件回退(Token storage: keychain),不会把文件回退伪装成安全存储。

OTLP 编码:严格的 protobuf-JSON 映射

同步载荷采用 OTLP/HTTP JSON 传输,即ExportTraceServiceRequest的严格 protobuf-JSON 映射:lowerCamelCase 字段、十六进制 ID、整数枚举。构建器位于 otlp.ts。

确定性 span / trace ID:重发即幂等

span_id = first 8 bytes of SHA-256(deduplicationKey) → hex (16 chars) trace_id = first 16 bytes of SHA-256(sessionId) → hex (32 chars)

对应源码 deriveSpanId 与 deriveTraceId。由于 ID 由内容派生而非随机生成,重发的 span 逐字节一致,服务端按 span ID 去重成为纵深防御(defense-in-depth)。

Resource 属性

{ "resource": { "attributes": [ { "key": "codeburn.device_id", "value": { "stringValue": "<SHA-256(hostname+username)[:16]>" } }, { "key": "codeburn.coverage_through", "value": { "stringValue": "2026-08-24" } } ] } }
  • codeburn.device_id是伪匿名的设备标识,派生自hostname + username的 SHA-256 前 16 位(deriveDeviceId),区分不同机器但绝不暴露主机名。
  • codeburn.coverage_through可选:本地语料完整覆盖到的 ISO 日期,取自 daily-cache 水位线;仅当一次完整本地解析固化该水位线(completewatermarkTrusted均置位)时才打上。接收端必须把缺失解释为「覆盖情况未知」,绝不能解释为「没有历史」。

Span 属性

{ "attributes": [ { "key": "ai.provider", "value": { "stringValue": "kiro" } }, { "key": "ai.model", "value": { "stringValue": "claude-sonnet-4-6" } }, { "key": "ai.input_tokens", "value": { "intValue": "12500" } }, { "key": "ai.output_tokens", "value": { "intValue": "3200" } }, { "key": "ai.cost_usd", "value": { "doubleValue": 0.085 } }, { "key": "ai.project", "value": { "stringValue": "my-app" } }, { "key": "ai.tools", "value": { "arrayValue": { "values": [{ "stringValue": "Edit" }] } } }, { "key": "ai.speed", "value": { "stringValue": "standard" } }, { "key": "ai.cost_estimated", "value": { "boolValue": true } }, { "key": "ai.work_unit_id", "value": { "stringValue": "ff1b1358ef64c52f80e50e7ae47ca176" } }, { "key": "ai.session_role", "value": { "stringValue": "child" } }, { "key": "ai.lineage_evidence", "value": { "stringValue": "provider-recorded" } }, { "key": "ai.cache_read_tokens", "value": { "intValue": "800" } }, { "key": "ai.cache_write_tokens", "value": { "intValue": "200" } }, { "key": "ai.call_count", "value": { "intValue": "3" } }, { "key": "ai.session_duration_ms", "value": { "intValue": "61000" } }, { "key": "ai.subscription_covered", "value": { "boolValue": true } } ] }

可选属性的精确语义:只有「被证明」才发送

ai.work_unit_id往下的每个属性都是可选的,只有在值被证明时才发送;一个忽略未知属性的旧接收端不会损失任何语义。逐条解读(继承自 docs/sync/DEVELOPER.md,并有 otlp.ts 与 push.ts 的源码佐证):

  • ai.work_unit_id/ai.session_role/ai.lineage_evidence:三者为整体(要么全发要么全不发),只对提供方在磁盘上持久记录了血缘(lineage)的会话发出(issue #1140)。ai.work_unit_id是 #1145 work-unit 解析器对根会话 ID 的deriveTraceId结果——与线上 trace id 采用同一种派生,因此一个 work unit 的身份与线上已有的根 trace 一致。血缘永不推断:无血缘记录的会话三者皆无;父会话超出范围(或链接歧义、成环)的子会话同样 fail-closed,三者皆无。push.ts 的 lineageContext 实现了这套解析。
  • ai.cache_read_tokens/ai.cache_write_tokens:提供方记录的缓存 token 数,与ai.input_tokens保持可计费一致——缓存读取采用展示层的max(cacheReadInputTokens, cachedInputTokens)约定,统一 Anthropic 与 OpenAI 两套词汇(见 otlp.ts 的Math.max实现)。各自仅在非零时发送。
  • ai.call_count:该 span 所属会话在同步窗口内贡献的 usage span 数。ai.session_duration_ms:该会话「最后一个减去第一个」的提供方记录事件时间,任一端缺失或乱序时省略(push.ts)。
  • ai.subscription_covered:plan/proxy-path 机制的判定结果——配置的 plan 覆盖了调用的提供方、或会话的提供方记录 cwd 位于配置的代理路径之下时为true,两者均被排除时为false,机制无法判定(无 plan 匹配且无 cwd 可查)时省略该属性。对应 subscriptionCoveredFor。
  • ai.output_tokens是可计费输出总量:对「推理 token 单独计费」的提供方(如 Anthropic 词汇),codeburn 会把推理量计入该字段;响应计数已含推理的提供方保持不变。实现见 otlp.ts 对billableOutputTokens的调用(与展示层 #1115/#1116 的计费口径一致)。
  • ai.project可选:仅当 codeburn 能从提供方记录的绝对工作目录派生出一个安全的 basename 时才出现;归属(attribution)span 只从归一化的git.repo派生它;仅有 PR 证据时省略。接收端必须把缺失项目归入「未归属」,不得要求该字段。当同一 trace 的 usage 与 attribution span 携带不同的安全 basename 时(例如 fork 检出目录名与上游仓库不同),attribution span 的归一化git.repobasename 对项目聚合具备最终权威——usage cwd basename 只是临时标签,接收端不得把两者计为两个独立项目。

值得一提的还有ai.cost_estimated:源码中当提供方为kiro(字符级估算)或输入 token 为 0 时置为true(otlp.ts),明确告知接收端成本是估算而非提供方直报。

出站标识符清洗(sanitizer)

OTLP 载荷里的 provider/model/tool 标识符全部经过 sanitizeIdentifier 及配套函数清洗:拒绝路径形态、URL 形态、凭据形态、绝对路径、控制字符与超长值;isEmailOrCredentialShaped(otlp.ts)还拦截邮箱形、ghp_sk-AKIA…等密钥前缀。project basename 同样受 projectBasenameFromWorkingDirectory 与isTrustedAbsoluteWorkingDirectory(见 path-privacy.ts)双重把关——伪造的、从提示词文本解析出的路径永远不会成为可信 provenance,也永远不会产生出站ai.project

Sent-Ledger:客户端去重的事实来源

sent-ledger 位于~/.cache/codeburn/sync-ledger.json,是客户端去重的唯一事实来源。

格式{ key: string, ts: string }对象的 JSON 数组。

Push 逻辑:收集窗口内全部调用 → 减去 ledger 中已有条目 → 发送剩余部分 → 成功后把deduplicationKey追加进 ledger。

剪枝:每次 push 时删除早于 6 个月的条目(appendToLedger 中SIX_MONTHS_MS常量)。

为什么不用时间戳水位线?时间戳水位线会静默跳过晚到的调用(长会话、提供方事后更新行记录的场景)。ledger 是精确的:以 key 为单位精确去重,晚到的调用下个窗口照发。

源码层面的两个加固值得一提:

  • 原子写入:ledger 先写临时文件再renameSync(ledger.ts),崩溃不会损坏账本——损坏的账本会被读成空,最坏情况是整个窗口重发而非数据丢失。
  • 旧路径迁移:在共享缓存解析器引入之前,ledger 曾位于 XDG_CACHE_HOME 下;readLedger 会把旧位置作为一次性迁移源合并进新位置(保留旧 key 防止升级后重复上传),同时确保CODEBURN_CACHE_DIR权威时绝不从不相关的 XDG 树导入。

部分成功(partial success)

OTLP 响应体可能携带partial_success.rejected_spans。由于 OTLP不指明具体哪些 span 被拒,客户端对部分拒绝的批次不记入 ledger——整个批次在下一次 push 时重试。这是安全的:span ID 由 deduplication key 确定性派生,按 span ID 存储的服务端会把重发 span 视为幂等 upsert。实现见 sendBatchesCore,其中还处理了 proto3 int64 的字符串编码问题(Number()转换避免字符串拼接)。

限流(429)与失败语义

一次 push 会跑到完成——没有常规的单次上限(仅 50,000 调用的安全阀MAX_PER_PUSH,见 push.ts)。服务端限流是预期的刹车机制:

  • 收到 HTTP 429 时客户端遵守Retry-After(delta-seconds 或 HTTP-date 皆可,解析见 parseRetryAfterMs),单次等待上限 120 秒;头部缺失时默认等待 5 秒;
  • 同一批次最多连续重试 3 次;若服务端仍在限流,push 停止,剩余(未记账)调用在下次 push 时继续;
  • 收到 401 或 5xx 时 push 立即停止,同样「下次 push 续传」。

服务端契约

后端必须实现两件事:

  1. GET {baseUrl}/.well-known/codeburn-export.json—— 返回发现文档(公开、无需认证);
  2. POST {baseUrl}{traces_path}—— 接受携带 Bearer token 的 OTLP/HTTP JSON,并且:
    • 校验 JWT(由配置的 IdP 签发);
    • 从 token 的sub声明派生开发者身份;
    • 接受最早不超过 6 个月的startTimeUnixNano
    • 返回标准 OTLP 响应体。

载荷中不包含任何 PII——服务端只能从已认证的 token 推导身份。注意同步还支持插件扩展点(plugin socket):插件只能携带其在 manifest 中声明的属性,CORE_SYNC_ATTRIBUTE_KEYS 与 filterPluginAttributes 构成出站守卫——插件不能伪造成本、token 或血缘字段。

Git Attribution(--attribution选填能力)

codeburn sync push --attribution会额外发送codeburn yield在本地计算的会话→提交关联,让后端无需 git hooks 即可把 AI 用量与 git 活动关联。其细节在 docs/sync/README.md 有完整定义,载荷构建实现位于 otlp.ts:

  • codeburn.session.attribution(每会话一条):携带ai.project(来自归一化git.repo的 basename)、git.repo(归一化 origin 远端,剥离凭据与端口)、git.pr_links(会话捕获的 PR URL)、git.commit_count
  • codeburn.commit(每个被归属的提交一条):携带git.shagit.in_maingit.was_reverted

归属是推断的(时间窗口关联,与codeburn yield同一启发式),resource 属性codeburn.attribution_methodology: timestamp-window明确标记了这一性质。状态迁移(提交合入 main、被 revert)会在后续 push 自动重发——接收端应按(git.repo, git.sha)upsert 提交、按traceIdupsert 会话 span(最新状态胜出)。会话 span 的 dedup key 编码了可变状态(sessionAttributionKey),因此「同一事实发一次、状态变化重发更新后的事实」。当提交迁移到窗口更紧的后续解析会话时,落败会话以git.commit_count: 0重发(即撤回),求和时不会重复计数。

出站边界非常严格:只发带网络origin远端的仓库提交、只发 cwd provenance 可信的会话;本地分组标签、提供方存储路径、提示词文本、纯本地仓库、file://远端与 Windows 文件系统路径永远不作为仓库身份出站。PR 链接仅由 scheme + host + path 重建(丢弃 userinfo、query、fragment;限https/org/repo/pull/N形态、长度有界、每会话最多 20 条),仓库身份通过严格的主机名/路径白名单,ext::…codecommit::…等 transport-helper 远端直接拒绝而非解析。不带--attribution时,以上一概不发。

测试策略:从纯函数到真实 Cognito 的四层防线

docs/sync/DEVELOPER.md 定义了清晰的测试分层,测试文件位于 tests/:

  1. 单元测试(tests/sync.test.ts,26 个用例):覆盖纯函数——发现文档解析、PKCE 生成、认证 URL 构造、scope 解析、回调服务器、配置读写。无网络、无浏览器。
  2. Mock IdP e2e(tests/sync-e2e.test.ts,6 个用例):基于 localhost mock IdP 服务器,完整演练认证往返、令牌刷新、轮换、撤销——完全离线,可在 CI 运行。
  3. 无头浏览器 e2e(tests/sync-headless-e2e.test.ts,1 个用例):Playwright headless Chromium 直连真实 Cognito,证明真实的浏览器 PKCE 流程(含 Cognito Hosted UI 表单提交与 localhost 重定向)可用。仅限开发者本地运行,需要:已部署的测试后端(独立 CDK stack)、已确认密码的 Cognito 用户、环境变量CODEBURN_SYNC_URL/CODEBURN_SYNC_EMAIL/CODEBURN_SYNC_PASSWORD、已安装的 Playwright Chromium(PLAYWRIGHT_BROWSERS_PATH)。未设置环境变量时默认跳过,永不进 CI
  4. 测试 CDK stack(仓库外codeburn-sync-backend/:为无头 e2e 准备的最小 AWS 后端——Cognito User Pool(PKCE、固定回调端口)、带 JWT authorizer 的 HTTP API、Discovery Lambda(提供codeburn-export.json)、Ingest Lambda(把 OTLP span 记入 CloudWatch)。部署命令npx cdk deploy --profile andklee-dev,空闲成本约 $0/月(按请求付费)。这是测试夹具而非生产参考——任何 OIDC 提供方 + 接受 OTLP 的端点都满足服务端契约。

测试还覆盖了推送管线的更多边界:tests/sync-attribution.test.tstests/sync-push.test.tstests/sync-consent.test.tstests/sync-wire-privacy.test.tstests/sync-project-provenance.test.ts等(见 tests/ 目录),分别验证归属载荷、推送语义、同意机制与线上隐私边界。

隐私边界与 FAQ 要点

从 docs/sync/README.md 提炼几条关键契约:

  • 绝不上传:提示词(prompts)、代码(内容/差异/路径)、bash 命令(可能含密钥)、姓名/邮箱(身份由服务端从登录 token 派生)。没有覆盖这些边界的开关——隐私是结构性的,不是可配置项。
  • 唯一增量式 opt-in 是--attribution(远端、提交 SHA、PR URL——绝无代码或提示词)。
  • 同步不会自动运行:未来版本可能提供机会式推送(每次codeburn report后),但始终是显式行为。
  • 重复推送同一窗口是安全的:sent-ledger 去重,不会产生重复。
  • Copilot 会话因本地对账在会话期持续变化(push.ts 的RECONCILE_SETTLE_MS),会静默 24 小时后再一次性推送最终形态;--dry-run会报告被 hold 的调用数。同理,Copilot 会话的输入/缓存只以「rollup 汇总」或「按请求拆分」其中一种形态出站(push.ts),且该选择一旦同步便永久固化,防止接收端同时持有两种形态导致重复计数。

快速上手回顾

# 一次性配置(打开浏览器登录) codeburn sync setup https://metrics.your-team.com # 推送最近 7 天的用量(默认窗口) codeburn sync push # 更大窗口 / 预览 / 附带 git 归属 codeburn sync push --since 30d codeburn sync push --dry-run codeburn sync push --attribution # 查看配置与认证状态 codeburn sync status # 注销(删除凭据并在 IdP 撤销令牌) codeburn sync logout # 清空已发送账本,强制窗口内全部重发(后端迁移或怀疑丢数据时用) codeburn sync reset --confirm

codeburn sync reset --confirm会清空本地 ledger 并以新口径重发一切——但只有当接收端副本也同时清空时才有意义,否则会产生它本要避免的数据翻倍。相关 CLI 注册见 src/sync/cli.ts。

小结

codeburn sync是一个「本地优先、显式推送、隐私结构性受控」的团队遥测通道:自定义发现文档解耦指标端点与 IdP,标准 OIDC + PKCE 提供认证,OS 原生存储保管凭据,确定性 OTLP span 编码让重发天然幂等,sent-ledger 提供精确到 key 的去重,429 限流与部分成功语义保证任意规模的 push 都能跑到完成。如果你想自建后端,只需实现一个公开发现文档与一个接受 Bearer token 的 OTLP 端点即可——任何 OIDC 提供方都能接入。

【免费下载链接】codeburn

Free, local tool to track AI coding token usage and cost across 37 tools and agents (Claude Code, Cursor, Codex, Gemini and more), by model, project, and task. npx codeburn

项目地址:https://gitcode.com/gh_mirrors/co/codeburn
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询