| 实例 | 状态 | PID | user data dir | 最近启动 | 操作 |
|---|
浏览器实例
启动、观察并安全管理 Chrome 与 Edge 环境
commit f8aaaeda2113fa094b1bcf9365bc4bf55a13d453 Author: QiuSW <105186638@qq.com> Date: Wed Jul 22 14:51:11 2026 +0800 chore: establish chub go foundation diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..eb6176a --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +build/ +dist/ +*.exe +*.log +*.db +*.db-* +.vscode/ +.idea/ + diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..7f30cad --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,5 @@ +# Chub Agent 规则 + +开始工作前必须阅读 [`docs/00-ai-start-here.md`](docs/00-ai-start-here.md)、[`docs/05-coding-rules.md`](docs/05-coding-rules.md)、[`docs/current-state.md`](docs/current-state.md) 和当前任务文件。 + +需求、架构、API 和验收文档是编码约束。所有进程控制必须限制在用户明确授权的实例范围内;禁止按进程名批量终止系统中的全部 Chrome/Edge。 diff --git a/README.md b/README.md new file mode 100644 index 0000000..d9e0756 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# Chub 浏览器实例管理工具 + +Chub 是面向 Windows 桌面和本地自动化场景的 Chrome/Edge 实例启动与生命周期管理工具。它支持指定浏览器可执行文件、`user-data-dir`、profile、启动 URL、代理和额外参数,并安全管理由工具启动的实例。 + +当前处于文档与交互原型阶段,尚未开始生产代码实现。 + +文档入口:[`docs/README.md`](docs/README.md)。MVP 闭环是“配置实例 -> 启动 -> 查看状态 -> 优雅关闭/强制关闭/重启”。首版不保存密码、Cookie、Token,不做平台自动登录和 RPA。 diff --git a/cmd/chub/main.go b/cmd/chub/main.go new file mode 100644 index 0000000..bb92dd7 --- /dev/null +++ b/cmd/chub/main.go @@ -0,0 +1,18 @@ +package main + +import ( + "context" + "fmt" + "os" + + "chub/internal/platform/logging" +) + +const version = "0.1.0-dev" + +func main() { + ctx := context.Background() + logger := logging.New(os.Stderr) + logger.InfoContext(ctx, "chub starting", "version", version) + fmt.Printf("Chub %s\n", version) +} diff --git a/docs/00-ai-start-here.md b/docs/00-ai-start-here.md new file mode 100644 index 0000000..367ddb3 --- /dev/null +++ b/docs/00-ai-start-here.md @@ -0,0 +1,30 @@ +# AI 开发入口 + +Chub 是 Windows 本地 Chrome/Edge 实例管理工具。第一版只做:配置并启动浏览器实例、查看工具管理的实例、检测 profile 占用、优雅关闭/强制关闭/重启和状态事件。 + +## 必读顺序 + +1. 根目录 `AGENTS.md` +2. [`01-vision.md`](01-vision.md) +3. [`02-requirements.md`](02-requirements.md) +4. [`03-tech-stack.md`](03-tech-stack.md) +5. [`04-architecture.md`](04-architecture.md) +6. [`05-coding-rules.md`](05-coding-rules.md) +7. 与任务相关的 [`api.md`](api.md)、[`07-user-stories.md`](07-user-stories.md) 和 [`08-interaction-checklist.md`](08-interaction-checklist.md) +8. [`06-tasks.md`](06-tasks.md)、任务文件和 [`current-state.md`](current-state.md) + +## 固定开工流程 + +1. 确认当前目录为 `D:\OPC\chub`。 +2. 检查 Git 状态和最近提交,不覆盖已有未提交改动。 +3. 读取当前状态,确认基线和 blocker。 +4. 领取一个依赖已完成的 TODO 任务,编辑任务状态为 DOING。 +5. 完成代码、测试和任务中列出的 Windows smoke 后再标记 DONE。 +6. 将验证结果写入任务文件,并更新 `current-state.md`。 + +## 关键边界 + +- 只管理本工具启动并注册的实例;外部实例默认只检测,不接管。 +- 禁止执行 `taskkill /IM chrome.exe`、`/IM msedge.exe` 或等价的全局终止。 +- 不把密码、Cookie、Token 或代理认证信息写入配置、日志、命令行或事件。 +- UI 不执行 I/O;浏览器启动、进程查询和关闭均在后台任务中完成。 diff --git a/docs/01-vision.md b/docs/01-vision.md new file mode 100644 index 0000000..2ba8c29 --- /dev/null +++ b/docs/01-vision.md @@ -0,0 +1,21 @@ +# 产品愿景 + +Chub 为 Windows 用户提供一个可复用的浏览器实例控制层,将 Chrome/Edge 的可执行文件、`user-data-dir`、profile、启动参数和生命周期统一管理。 + +## 用户 + +- 需要同时运行多个隔离浏览器环境的运营和测试人员。 +- 需要脚本可靠启动和回收浏览器的开发人员。 +- 需要桌面化观察浏览器状态的维护人员。 + +## 原则 + +1. 实例身份优先:PID、命令行、浏览器类型和 user data dir 必须能互相校验。 +2. 安全关闭优先:先优雅关闭,明确确认后才强制终止。 +3. 外部进程不误伤:不按进程名全局操作。 +4. 参数透明:展示实际启动参数,但隐藏敏感信息。 +5. 本地优先:MVP 不需要云服务和平台账号。 + +## 非目标 + +首版不保存凭证、不自动登录、不绕过验证码、不做反指纹/防关联、不做平台 RPA、不承诺接管任意外部浏览器、不做远程主机进程管理。 diff --git a/docs/02-requirements.md b/docs/02-requirements.md new file mode 100644 index 0000000..da45d0e --- /dev/null +++ b/docs/02-requirements.md @@ -0,0 +1,29 @@ +# 产品需求 + +| ID | 需求 | 优先级 | +| --- | --- | --- | +| BR-001 | 支持 Chrome 和 Edge,允许自动发现或手动指定 executable。 | P0 | +| BR-002 | 启动配置支持 `user-data-dir`、`profile-directory`、URL、代理、headless 和额外参数。 | P0 | +| BR-003 | 启动前检测目标 user data dir 是否占用,禁止同一环境重复启动。 | P0 | +| BR-004 | 实例列表显示浏览器类型、PID、user data dir、启动时间和状态。 | P0 | +| BR-005 | 支持优雅关闭、强制关闭和重启,并明确操作影响。 | P0 | +| BR-006 | 监控启动失败、异常退出、退出码和进程消失。 | P0 | +| BR-007 | 启动参数按数组传递,不通过 shell 拼接。 | P0 | +| BR-008 | 只允许管理工具注册且经过身份校验的 PID。 | P0 | +| BR-009 | 支持本地配置持久化,绝不保存浏览器凭证。 | P1 | +| BR-010 | 提供 CLI 或本地 API,供脚本启动、查询和关闭实例。 | P1 | +| BR-011 | 可选启用本地 CDP,用于读取窗口/tab 信息;默认关闭。 | P2 | + +## 验收标准 + +- 两个不同 user data dir 可以并行启动,互不阻塞。 +- 同一 user data dir 的第二次启动被拒绝,并显示已知 PID/来源。 +- 关闭操作不会影响其他 Chrome/Edge 实例。 +- 工具重启后,无法确认身份的外部进程只能报告 UNKNOWN,不得被关闭。 +- 异常退出后状态在合理时间内变为 EXITED/FAILED。 +- 参数中不出现密码、Cookie、Token 或代理 userinfo。 +- UI 覆盖加载、空、占用、启动失败、关闭中、成功和权限错误。 + +## 不做 + +全局杀 Chrome/Edge、自动登录、页面操作、验证码处理、平台 API 集成、远程控制和跨用户权限提升。 diff --git a/docs/03-tech-stack.md b/docs/03-tech-stack.md new file mode 100644 index 0000000..2a0c998 --- /dev/null +++ b/docs/03-tech-stack.md @@ -0,0 +1,23 @@ +# 技术栈与验证 + +| 层 | 选择 | 约束 | +| --- | --- | --- | +| 核心 | Go 1.23(当前基线) | 标准库优先,Windows API 通过小型适配层封装;升级到 Go 1.25+ 需重新验证构建。 | +| Windows UI | Go Gio(版本待锁定) | UI 线程不执行进程和文件 I/O;实现前制作 HTML 原型。 | +| 持久化 | SQLite 或 JSON(MVP 前决策) | 配置不保存密码、Cookie、Token。 | +| 进程 | `os/exec` + Windows API | 参数数组启动;Job Object、窗口消息和句柄按职责封装。 | +| API | 本地 CLI,后续可选 loopback HTTP/WebSocket | 默认只监听本机。 | + +## 验证命令 + +建立代码后同步并执行: + +```powershell +go test ./... +go vet ./... +go build ./cmd/chub +``` + +Windows smoke 至少覆盖真实 Chrome/Edge 临时 user data dir、双实例、重复占用、优雅关闭、强制关闭和异常退出。 + +新增依赖必须说明版本、许可证、Windows 兼容性和打包影响。核心启动和身份校验优先使用标准库和 Win32 API。 diff --git a/docs/04-architecture.md b/docs/04-architecture.md new file mode 100644 index 0000000..375aa76 --- /dev/null +++ b/docs/04-architecture.md @@ -0,0 +1,41 @@ +# 架构设计 + +```text +Gio UI / CLI + ↓ DTO + commands +Application BrowserManager + ↓ ports +Platform Windows + ├─ executable discovery + ├─ launcher + ├─ process identity / query + ├─ graceful close / force kill + ├─ Job Object + └─ profile occupancy inspector + ↓ +Chrome / Edge processes +``` + +UI/CLI 不直接操作 `exec.Cmd`、Win32 handle 或数据库。Application 层维护实例状态和授权边界;Platform 层只提供系统能力。 + +## 实例身份 + +每个实例至少记录 `instance_id`、browser kind、executable、root PID、user data dir、profile directory、非敏感参数摘要、创建时间、状态和退出码。 + +进程身份校验至少比较 PID 存活、executable、命令行中的规范化 `--user-data-dir` 和注册记录。无法确认身份时只能报告 UNKNOWN,不允许关闭。 + +## 生命周期 + +`CREATED -> STARTING -> RUNNING -> STOPPING -> EXITED`;启动失败为 `FAILED`,无法确认的外部实例为 `UNKNOWN`。 + +- Start:规范化路径和参数,检查 user data dir,占用检查通过后注册 pending,再启动。 +- Stop:校验身份,优先窗口关闭/浏览器协议,超时后经明确授权强制终止。 +- Force stop:使用实例 Job Object 或已校验进程树,不按名称全局终止。 +- Restart:旧实例退出或完成超时处理后重新执行同一配置。 +- App shutdown:取消监控,不默认终止用户浏览器。 + +Chrome 和 Edge 共用大部分 Chromium 参数,但 executable 默认路径、进程名称和安装方式不同,通过 `BrowserDefinition` 封装差异。 + +## 风险 + +Chromium 可能复用已有进程;浏览器是多进程架构;管理员权限进程可能无法查询;强制终止可能损坏 profile;CDP 端口开放到非 loopback 会形成控制风险,MVP 默认关闭。 diff --git a/docs/05-coding-rules.md b/docs/05-coding-rules.md new file mode 100644 index 0000000..6c1b06b --- /dev/null +++ b/docs/05-coding-rules.md @@ -0,0 +1,14 @@ +# 编码规则 + +1. 启动参数使用 `exec.Command(executable, args...)`,不拼 shell 字符串。 +2. 关闭前必须校验 PID、executable 和 user data dir;无法确认则拒绝。 +3. 禁止 `taskkill /IM chrome.exe`、`/IM msedge.exe` 或等效全局终止。 +4. 默认不接管外部实例;接管能力必须新增需求、安全评审和测试。 +5. 日志、错误、事件和持久化不得包含密码、Cookie、Token、代理认证或完整秘密参数。 +6. 用户路径必须规范化并有绝对路径、权限和 Windows 长路径测试。 +7. I/O 方法接收 `context.Context`,取消管理任务不能隐式杀死浏览器。 +8. 每个实例最多一个监控 goroutine;退出后释放 registry 和句柄。 +9. 不在 UI frame 或事件回调中执行阻塞 I/O;共享状态必须有明确所有权。 +10. 错误使用稳定 code 或 typed error,底层 cause 只进入诊断日志。 +11. UI 的加载、空、失败、确认和恢复路径必须写入交互清单。 +12. API 使用 DTO,不暴露平台句柄、SQL 行或原始系统堆栈。 diff --git a/docs/06-tasks.md b/docs/06-tasks.md new file mode 100644 index 0000000..d0a23b5 --- /dev/null +++ b/docs/06-tasks.md @@ -0,0 +1,33 @@ +# 任务路线图 + +状态:TODO、DOING、DONE、BLOCKED。未启用协作服务时以 `docs/tasks/T-<编号>.md` 为单任务权威。 + +## Phase 0:地基 + +| ID | 任务 | 依赖 | 状态 | +| --- | --- | --- | --- | +| T-001 | 建立 Go module、命令入口、日志和测试基座 | - | TODO | +| T-002 | 固化 BrowserDefinition、LaunchSpec、错误和事件合约 | T-001 | TODO | +| T-003 | 实现可测试的参数构造和 Chrome/Edge 发现 | T-002 | TODO | + +## Phase 1:进程核心 + +| ID | 任务 | 依赖 | 状态 | +| --- | --- | --- | --- | +| T-101 | 实现启动、registry、Wait 和 profile 占用检测 | T-003 | TODO | +| T-102 | 实现 Windows 进程身份查询和外部实例保守识别 | T-101 | TODO | +| T-103 | 实现优雅关闭、强制关闭和 Job Object 进程树 | T-102 | TODO | +| T-104 | Chrome/Edge 双实例、异常退出和权限失败 smoke | T-103 | TODO | + +## Phase 2:产品外壳 + +| ID | 任务 | 依赖 | 状态 | +| --- | --- | --- | --- | +| T-201 | HTML 原型、Gio 外壳和实例列表/表单 | T-002 | TODO | +| T-202 | 本地配置持久化和实例恢复 | T-101 | TODO | +| T-203 | CLI 合约和本地事件推送 | T-103 | TODO | +| T-204 | UI 全状态验收与 Windows 打包 smoke | T-201,T-202,T-203 | TODO | + +## Backlog + +CDP tab/window 管理、导入导出启动配置、进程资源监控、多用户权限和远程主机管理。 diff --git a/docs/07-user-stories.md b/docs/07-user-stories.md new file mode 100644 index 0000000..65189b2 --- /dev/null +++ b/docs/07-user-stories.md @@ -0,0 +1,24 @@ +# 用户故事 + +| ID | 用户故事 | 优先级 | +| --- | --- | --- | +| US-001 | 用户可以创建 Chrome/Edge 实例配置,并指定 user data dir、profile 和 URL。 | P0 | +| US-002 | 用户可以启动两个不同隔离环境,并看到各自 PID 和运行状态。 | P0 | +| US-003 | 用户可以发现同一 user data dir 已被占用,避免重复启动。 | P0 | +| US-004 | 用户可以优雅关闭实例;无响应时在确认后强制终止。 | P0 | +| US-005 | 用户可以重启指定实例,并确认旧实例已经退出。 | P0 | +| US-006 | 用户可以通过 CLI/API 查询、启动和关闭实例。 | P1 | + +## 验收场景 + +### US-003 占用保护 + +给定一个已运行的 Chrome/Edge,使用相同规范化 user data dir 启动时,系统拒绝第二次启动,显示已知 PID 和占用来源,并保留原配置。 + +### US-004 安全关闭 + +用户点击关闭后按钮进入 STOPPING;浏览器正常退出则显示 EXITED;等待超时后只显示强制终止确认,不自动扩大关闭范围。 + +### US-006 CLI/API + +CLI/API 返回稳定错误码和结构化数据;未知 PID、身份不匹配和权限不足必须拒绝操作并给出恢复建议。 diff --git a/docs/08-interaction-checklist.md b/docs/08-interaction-checklist.md new file mode 100644 index 0000000..d48d290 --- /dev/null +++ b/docs/08-interaction-checklist.md @@ -0,0 +1,18 @@ +# 交互清单 + +| ID | 页面/组件 | 交互 | 状态覆盖 | 优先级 | +| --- | --- | --- | --- | --- | +| IX-001 | 实例列表 | 新建、启动、刷新、查看详情 | 加载、空、运行、退出、失败 | P0 | +| IX-002 | 启动表单 | 浏览器类型、路径、user data dir、URL、参数校验 | 默认、校验错误、提交中、成功 | P0 | +| IX-003 | 实例详情 | 优雅关闭、强制终止、重启 | 运行中、关闭中、超时确认、权限错误 | P0 | +| IX-004 | 占用提示 | 查看 PID/来源并重试 | 被占用、身份未知、已释放 | P0 | +| IX-005 | 设置 | 默认路径、日志和数据目录 | 保存成功、路径无效、权限拒绝 | P1 | + +## 通用规则 + +- 异步操作不阻塞窗口线程,提交中禁用重复按钮。 +- 危险操作说明影响范围,默认焦点在取消;Escape 可取消。 +- 进程状态同时使用文字、图标和颜色,不只用颜色表达。 +- 关闭完成后焦点回到实例行;失败时保留表单和用户输入。 +- 验证 960x640、600x500、100%–200% 缩放、键盘、深色和高对比度回退。 +- 不依赖悬停或触控手势完成关键任务。 diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..75e4414 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,21 @@ +# 项目文档导航 + +Chub 是 Windows 本地 Chrome/Edge 实例管理工具,首版闭环是“配置实例 -> 启动 -> 查看状态 -> 关闭/重启”。 + +| 文档 | 职责 | +| --- | --- | +| [`00-ai-start-here.md`](00-ai-start-here.md) | agent 阅读顺序和开工流程 | +| [`01-vision.md`](01-vision.md) | 产品目标、用户和非目标 | +| [`02-requirements.md`](02-requirements.md) | 功能范围、优先级和验收 | +| [`03-tech-stack.md`](03-tech-stack.md) | 技术选型和验证命令 | +| [`04-architecture.md`](04-architecture.md) | 分层、模块、进程模型和数据流 | +| [`05-coding-rules.md`](05-coding-rules.md) | 安全、Windows、Go 和 UI 规则 | +| [`06-tasks.md`](06-tasks.md) | 阶段路线图和任务池 | +| [`07-user-stories.md`](07-user-stories.md) | 用户故事与验收场景 | +| [`08-interaction-checklist.md`](08-interaction-checklist.md) | 页面状态、交互和无障碍 | +| [`api.md`](api.md) | 本地模块、CLI、事件和错误合约 | +| [`current-state.md`](current-state.md) | 当前代码现实和下一步 | +| [`agent-context.json`](agent-context.json) | 机器可读上下文路由 | +| [`design/README.md`](design/README.md) | HTML 原型输入和交接规则 | +| [`ui/README.md`](ui/README.md) | Chub UI 原型、评审场景和 Gio 交接 | +| [`tasks/README.md`](tasks/README.md) | 一任务一文件约定 | diff --git a/docs/agent-context.json b/docs/agent-context.json new file mode 100644 index 0000000..871fc2c --- /dev/null +++ b/docs/agent-context.json @@ -0,0 +1,12 @@ +{ + "schema":"docs/agent-context.schema.json", + "schema_version":1, + "bootstrap":["AGENTS.md","docs/00-ai-start-here.md","docs/05-coding-rules.md","docs/current-state.md"], + "routes":{ + "documentation":["README.md","docs/README.md","docs/01-vision.md","docs/02-requirements.md","docs/07-user-stories.md","docs/08-interaction-checklist.md"], + "browser":["docs/02-requirements.md","docs/03-tech-stack.md","docs/04-architecture.md","docs/05-coding-rules.md","docs/api.md"], + "ui":["docs/07-user-stories.md","docs/08-interaction-checklist.md","docs/ui/README.md","docs/04-architecture.md"], + "deploy":["docs/03-tech-stack.md","docs/current-state.md"] + }, + "tasks":{"roadmap":"docs/06-tasks.md","directory":"docs/tasks/","template":"docs/tasks/_template.md"} +} diff --git a/docs/agent-context.md b/docs/agent-context.md new file mode 100644 index 0000000..aa13a2f --- /dev/null +++ b/docs/agent-context.md @@ -0,0 +1,7 @@ +# Agent 上下文清单 + +`agent-context.json` 是按任务类型选择文档的机器可读清单,Schema 位于 `agent-context.schema.json`。 + +首次接入读取 bootstrap;日常任务再读取对应 route 和唯一任务文件。需求以 `02-requirements.md` 为准,架构/API 以 `04-architecture.md` 与 `api.md` 为准,代码行为以测试和真实 Windows smoke 为准。 + +本项目未启用 Gitea 协调。任务状态以 `docs/tasks/T-<编号>.md` 的 frontmatter 和 `06-tasks.md` 为准;外部状态不可用时可以继续已领取任务,但不得猜测其他 agent 的写路径。 diff --git a/docs/agent-context.schema.json b/docs/agent-context.schema.json new file mode 100644 index 0000000..cb00103 --- /dev/null +++ b/docs/agent-context.schema.json @@ -0,0 +1,12 @@ +{ + "$schema":"https://json-schema.org/draft/2020-12/schema", + "type":"object", + "required":["schema","schema_version","bootstrap","routes","tasks"], + "properties":{ + "schema":{"const":"docs/agent-context.schema.json"}, + "schema_version":{"const":1}, + "bootstrap":{"type":"array","items":{"type":"string"},"minItems":1}, + "routes":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}, + "tasks":{"type":"object","required":["roadmap","directory","template"]} + } +} diff --git a/docs/api.md b/docs/api.md new file mode 100644 index 0000000..7b6aa4f --- /dev/null +++ b/docs/api.md @@ -0,0 +1,68 @@ +# API / 模块合约 + +MVP 首先提供本地 Go application service 和 CLI;是否增加 loopback HTTP/WebSocket 在 T-203 决策。时间使用 RFC3339,路径使用规范化绝对路径。 + +## 核心类型 + +```go +type BrowserKind string +const ( + BrowserChrome BrowserKind = "chrome" + BrowserEdge BrowserKind = "edge" +) + +type LaunchSpec struct { + Kind BrowserKind + Executable string + UserDataDir string + ProfileDirectory string + TargetURL string + ProxyServer string + Headless bool + ExtraArgs []string +} + +type InstanceView struct { + ID string + Kind BrowserKind + PID int + UserDataDir string + Status string + ExitCode *int +} +``` + +## Application service + +```go +type BrowserManager interface { + Start(ctx context.Context, spec LaunchSpec) (InstanceView, error) + List(ctx context.Context) ([]InstanceView, error) + Get(ctx context.Context, id string) (InstanceView, error) + Stop(ctx context.Context, id string, force bool) error + Restart(ctx context.Context, id string) (InstanceView, error) +} +``` + +`Stop(force=false)` 只执行优雅关闭;强制关闭必须由明确用户动作或 CLI `--force` 触发。 + +## CLI 目标形状 + +```text +chub start --browser chrome --user-data-dir
启动、观察并安全管理 Chrome 与 Edge 环境
| 实例 | 状态 | PID | user data dir | 最近启动 | 操作 |
|---|