- 前端
- 数据可视化
- 3D渲染
【免费下载链接】git-city
Your GitHub profile as a 3D pixel art building in an interactive city
Git City(git-city)是一个把 GitHub 个人主页映射为 3D 像素风建筑、并构建成可交互城市的前端项目。本文以仓库内packages/vscode-extension/CHANGELOG.md为骨架,结合扩展源码与服务端心跳接口,完整解读Git City: Pulse这款 VS Code 扩展从 0.1.0 到 0.3.0 的演进脉络:它如何通过心跳机制让"你的建筑在你编码时保持点亮"、如何追踪 AI Agent 与终端活动、如何以隐私优先的方式控制数据分享,以及每个版本背后的配置项、命令、状态栏语义与底层实现。读完你将掌握该扩展的完整工作原理、全部可配置参数与可复制的接入方式。
一、Git City: Pulse 在项目中的定位
在 Git City 的世界观里,每位开发者都拥有一座属于自己的 3D 像素建筑,建筑高度由贡献量决定,宽度由仓库数量决定,而点亮窗户、在实时流中出现的"在线存在感",则依赖本扩展发出的心跳信号。
扩展自身定位为"你的建筑的发射器(transmitter)"——packages/vscode-extension/package.json中的描述写道:"Keep your city alive. When you code, your building glows and powers the signal."。它并不负责渲染城市(那部分由 Web 端src/components/CityCanvas.tsx、src/components/Building3D.tsx等承担),而是持续检测你在 VS Code 中的编码活动,将其压缩成结构化心跳上报到服务端,再由服务端通过实时广播通道推送给城市页面(参见 心跳接口实现 与 前端实时订阅)。
VS Code 扩展(Pulse) Web 服务端 ───────────────────── ───────────────────────────────── 活动检测 → 脱敏 → 队列 → POST /api/heartbeats → developer_sessions 表 (tracker) (sanitizer) (queue/client) → Realtime 广播 → 城市页面点亮建筑二、0.1.0:初始版本的三块基石
首个版本确立了扩展的核心能力,也是后续所有演进的地基。CHANGELOG.md记录的四项能力在源码中均有完整对应实现。
1. 实时存在:编码即点亮
[活动追踪器](https://link.gitcode.com/i/61f45ad55966abe2563d8e890b5adaa1)订阅了 VS Code 的编辑器事件(文本变更、保存、选区变化、活动编辑器切换),并在事件到来时调度心跳。关键逻辑:
- 50ms 防抖:非写入事件先经过
DEBOUNCE_MS = 50的定时器合并,避免击键风暴产生海量请求(源码注释明确说明该模式借鉴自 WakaTime 的成熟实践); - 心跳触发条件:从空闲中唤醒、切换了文件、保存了文件、或距上次心跳已超过 120 秒(
HEARTBEAT_THROTTLE_MS = 2 * 60 * 1000,见 constants.ts); - 写入优先:
scheduleEvent(isWrite)对保存、文件创建/删除/重命名等显式写入事件跳过防抖直接处理。
每个心跳携带timestamp、language(编程语言)、project(项目名)、isWrite、activeSeconds、sessionId、editorName、os等字段(见 sanitizer.ts 中的RawHeartbeat定义)。
2. 隐私控制:分享什么由你决定
扩展从第一版就把隐私作为一等公民。心跳在离开本机前会经过sanitize()脱敏:关闭shareLanguage则删除语言字段;关闭shareProject则同时删除项目名与分支名;命中excludeProjects黑名单的项目同样被剥离。服务端在 presence 接口 中回应公共数据时刻意排除 project 与 developerId,只返回githubLogin、avatarUrl、status、language——这是"项目名永不公开"承诺的服务端兑现。
3. 状态栏集成与空闲检测
- 状态栏常驻显示当前发射状态,点击可切换暂停/恢复(
[状态栏实现](https://link.gitcode.com/i/4ab682b32c388c39a33b2ab470d6544b)); - 空闲检测由
resetIdleTimer()实现:每次事件重置定时器,超时未活动则从active迁移到idle,空闲阈值默认 300 秒(5 分钟),可通过gitCity.idleTimeout配置(范围 60–3600 秒); - 一个反直觉的设计:不追踪窗口焦点。源码注释说明,如果开发者把 VS Code 放在副屏,窗口失焦不应立刻判为离线,而应等到空闲超时自然触发——这让"挂机在编辑器里但确实在思考"的场景也能保持建筑点亮。
三、0.2.0:品牌重塑与状态语义重构
0.2.0 是一次面向"信号系统"的品牌升级,CHANGELOG.md记录了三个变化,全部可溯源到当前仓库:
1. 更名为 Git City: Pulse
扩展 displayName 正式定为Git City: Pulse(见 package.json),此前的命名不再沿用,README 与 CHANGELOG 均统一为新品牌。
2. 四态状态栏模型
[状态栏实现](https://link.gitcode.com/i/4ab682b32c388c39a33b2ab470d6544b)的updateDisplay()定义了四种展示态,对应 README 中的说明表格:
| 状态 | 图标 | 文案 | 语义 | 点击行为 |
|---|---|---|---|---|
| active | $(broadcast) | Pulse: Transmitting(可附(Nh Nm)累计时长) | 建筑正在城市中点亮 | 暂停(togglePause) |
| idle | $(circle-outline) | Pulse: Standby | 等待你编码 | 暂停 |
| paused | $(circle-slash) | Pulse: Off(警告色背景) | 发射器手动暂停 | 恢复 |
| connect | $(plug) | Pulse: Disconnected | 未设置 API Key | 弹出登录(login) |
其中active态的时长显示由 30 秒一次的updateTimer刷新,累计活跃秒数由 tracker 中每秒递增的activeSecondsTimer统计(仅在非暂停且距上次活动小于空闲阈值时累加)。
3. 命令更名与 API URL 修正
四类命令全部统一到Pulse:前缀(package.json 的contributes.commands):
gitCity.login→Pulse: Connect:弹窗粘贴 API Key(掩码输入、ignoreFocusOut),写入后立即发送一次即时心跳,并提示"See my building"跳转城市;gitCity.logout→Pulse: Disconnect:删除密钥并发送 offline 信号,让建筑立即从城市熄灭;gitCity.togglePause→Pulse: Toggle:切换暂停/恢复;gitCity.showDashboard→Pulse: Open City:浏览器打开城市首页。
"Fixed API URL to use www subdomain"对应配置默认值https://www.thegitcity.com(DEFAULT_API_URL,见 constants.ts)。该值同时作为登录成功后的跳转目标与心跳上报地址。
四、0.3.0:追踪维度全面扩展
0.3.0 是本文档信息的最新版本(当前扩展版本号为 0.3.0),其核心贡献是让"建筑点亮"不再局限于纯编辑器操作,而是覆盖现代开发中大量存在的AI Agent 协作与终端工作流。
1. 新增五类活动信号源
[活动追踪器](https://link.gitcode.com/i/61f45ad55966abe2563d8e890b5adaa1)的initTracker()在原有编辑器事件之外新增订阅:
- 终端活动(Terminal):
onDidStartTerminalShellExecution/onDidEndTerminalShellExecution/onDidOpenTerminal/onDidChangeActiveTerminal——覆盖 Claude Code、Cursor agent 以及手动执行命令的全部场景; - 调试会话(Debug):
onDidStartDebugSession/onDidTerminateDebugSession; - 任务运行器(Tasks):
onDidStartTask/onDidEndTask,即npm run、build、test 等; - 文件系统操作(Filesystem):
onDidCreateFiles/onDidDeleteFiles/onDidRenameFiles——专门捕捉 Agent 自动增删改文件的行为,且这些事件按isWrite=true处理,直接触发心跳; - Notebook 编辑:
onDidChangeNotebookDocument,覆盖 Jupyter 单元编辑。
2. "AI 编码时建筑保持点亮"的实现含义
CHANGELOG 中 "Your building now stays lit when coding via AI agents or terminal" 的落实机制:当 Claude Code / Cursor agent 在集成终端中执行命令、或通过文件系统修改文件时,上述事件同样进入scheduleEvent()管线,重置空闲计时器并推动心跳,使开发者即使"没在手动敲键盘",其建筑也维持Transmitting状态;反之,Agent 停止活动后,空闲计时器照常工作,建筑在gitCity.idleTimeout后自然转入 Standby。
3. 最低 VS Code 版本提升至 1.93
engines.vscode字段为^1.93.0,且@types/vscode同步锁定^1.93.0。这意味着本扩展依赖 1.93 引入的终端执行事件 API(onDidStartTerminalShellExecution等),使用低于该版本的 VS Code 无法安装或运行。
五、心跳管线底层原理:队列、重试与离线信号
综合 0.1.0–0.3.0 的演进,完整的心跳链路可拆为四层:
1. 队列层(api/queue.ts)
- 心跳先进内存队列并立即持久化到
context.globalState(键gitCity.pendingHeartbeats),保证崩溃不丢数据; - 队列非空时第一条心跳立即触发一次 flush("instant feedback",让开发者在登录后几秒内出现在站点上,对应 README 中"~30 seconds"的体验承诺);
- 此后每 30 秒(
FLUSH_INTERVAL_MS)批量发送,单批上限 25 条(MAX_BATCH_SIZE)。
2. 传输层(api/client.ts)
POST {apiUrl}/api/heartbeats,鉴权头为X-API-Key,Body 为心跳数组;- 最多重试 3 次,指数退避(1s → 2s);401/403 与 429 不重试——前者是密钥问题无需徒劳,后者是限流,交给时间自然恢复;
- 网络错误(fetch 抛异常)则按退避重试;全部失败后批量回插队列头部,等待下个周期再发。
3. 离线信号(extension.ts 的deactivate)
- 暂停、空闲、主动断开时,
transition()会发送status: "offline"的心跳,让服务端立即结束会话而非等待超时; - VS Code 关闭进程时,
deactivate()用getCachedKey()(同步缓存)绕过可能不可用的 SecretStorage,直接sendDirect()发送离线心跳——单次尝试、3 秒超时(AbortController),注释明言这是"best effort"。
4. 服务端校验(src/app/api/heartbeats/route.ts)
服务端对每条心跳做严格白名单校验:sessionId必填且 ≤128 字符;编辑器名限定vscode/cursor/vscodium/windsurf/positron;OS 限定darwin/linux/win32/freebsd/openbsd;activeSeconds截断到 0–3600;每批最多 25 条。API Key 通过sha256哈希后与developers.vscode_api_key_hash比对(服务端不存明文密钥)。时间戳由服务端生成,绝不信任客户端,并 upsert 到developer_sessions表累加total_heartbeats与active_seconds。广播侧做了 60 秒去抖,但离线信号总是立即广播,保证建筑熄灭即时生效。
六、完整配置参考(全部继承自 package.json)
以下配置项可直接在 VS Code 设置中搜索 "Git City" 修改(package.json 的contributes.configuration):
| 配置键 | 类型 | 默认值 | 说明 |
|---|---|---|---|
gitCity.enabled | boolean | true | 全局开关,关闭后完全停止活动追踪与传输 |
gitCity.apiUrl | string | https://www.thegitcity.com | API 地址(application 作用域);官方说明:修改它会将你的 API Key 发送到其他服务器,非必要勿改 |
gitCity.privacy.shareLanguage | boolean | true | 是否公开分享当前编程语言(会显示在你的建筑上) |
gitCity.privacy.shareProject | boolean | true | 是否发送项目名(仅用于个人统计,从不公开展示) |
gitCity.privacy.excludeProjects | string[] | [] | 永不追踪的项目名黑名单,如["secret-project", "client-work"](子串匹配、忽略大小写) |
gitCity.idleTimeout | number | 300 | 判定空闲的无活动秒数,范围 60–3600 |
隐私红线(README 明确承诺、源码可验证):文件内容、代码、diff、剪贴板、终端输出、文件路径、分支名永不收集;项目名仅存服务端用于个人分析,绝不出现在任何公共 API 或广播中。关闭shareProject后,sanitize()会同时剔除project与branch字段,双保险。
七、构建、打包与本地开发
扩展采用 esbuild 构建(esbuild.mjs):
npm run build:打包src/extension.ts到dist/extension.js(external: ["vscode"]、CJS、target: node18、生产模式压缩并输出 sourcemap);npm run watch:增量监听模式(--watch,不压缩便于调试);npm run package:调用vsce package生成可安装的.vsix。
TypeScript 侧开启strict模式,module: commonjs、target: ES2022(见 tsconfig.json)。activationEvents为onStartupFinished,即 VS Code 启动完成后自动激活,无需用户手动触发,从而保证"一打开编辑器就在持续检测活动"。
八、版本演进速览
| 版本 | 核心主题 | 关键变化 |
|---|---|---|
| 0.1.0 | 初始发布 | 实时存在(编码点亮建筑)、隐私控制、状态栏集成、可配置空闲检测 |
| 0.2.0 | 品牌重塑 | 更名 Git City: Pulse;四态状态栏(Transmitting/Standby/Off/Disconnected);命令统一 Pulse 前缀;API 域名修正为 www 子域 |
| 0.3.0 | 追踪扩展 | 新增终端(Claude Code/Cursor agent/手动命令)、调试会话、任务运行器、文件系统操作、Notebook 编辑五类信号源;AI 编码时建筑保持点亮;最低 VS Code 1.93 |
三版演进共同构成一条清晰的工程主线:先是把"在线"做对(心跳、脱敏、状态栏),再把"在线"做全(覆盖 Agent 与终端工作流),同时始终守住隐私边界(本机脱敏 + 服务端白名单 + 公共数据最小化)。对于希望自建编码存在感上报系统的开发者,packages/vscode-extension下的 tracker → sanitizer → queue → client 四层结构、src/app/api/heartbeats/route.ts的服务端校验模式,以及 presence 接口 的公共字段裁剪策略,都是可以直接借鉴的参考实现。
- 前端
- 数据可视化
- 3D渲染
【免费下载链接】git-city
Your GitHub profile as a 3D pixel art building in an interactive city
相关推荐
Nord 主题移植的完整演进史:从 VS Code 扩展到 Oni2 原生编辑器
Nord 主题移植的完整演进史:从 VS Code 扩展到 Oni2 原生编辑器 导读 本文以 Oni2 仓库中内置的 Nord 主题扩展( extension
开发工具代码编辑器桌面应用GitHub1s完整发展史:从零到一的VS Code在线编辑器演进历程
GitHub1s完整发展史:从零到一的VS Code在线编辑器演进历程 GitHub1s是一个革命性的开源项目,让你能够在一秒钟内用VS Code界面阅读Git
开发工具前端VS Code 1.54(2021 年 2 月)版本亮点深度解析:Apple Silicon、终端会话恢复与扩展 API 演进
VS Code 1.54(2021 年 2 月)版本亮点深度解析:Apple Silicon、终端会话恢复与扩展 API 演进 Visual Studio Co
文档教程
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考