# https://github.com/lvxiaoxin/copilot-sync 项目说明书

生成时间：2026-06-21 18:19:27 UTC

## 目录

- [项目概览与系统架构](#page-1)
- [CLI 命令与日常同步工作流](#page-2)
- [配置文件、Allow/Deny 清单与安全模型](#page-3)
- [会话历史同步与两种模式](#page-4)

<a id='page-1'></a>

## 项目概览与系统架构

### 相关页面

相关主题：[CLI 命令与日常同步工作流](#page-2), [配置文件、Allow/Deny 清单与安全模型](#page-3)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [package.json](https://github.com/lvxiaoxin/copilot-sync/blob/main/package.json)
- [README.md](https://github.com/lvxiaoxin/copilot-sync/blob/main/README.md)
- [src/manifest.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/manifest.js)
- [src/secrets.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/secrets.js)
- [src/history-store.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/history-store.js)
- [src/log.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/log.js)
- [src/commands/onboard.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/commands/onboard.js)
- [src/commands/push.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/commands/push.js)
- [src/prompt.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/prompt.js)
</details>

# 项目概览与系统架构

## 项目定位与目标

copilot-sync 是一个跨平台的命令行工具（CLI），定位为"在多台开发机器之间同步 GitHub Copilot CLI 的配置与会话历史"。它的核心理念是"在一台机器配置一次，到处复用"——通过用户自有的 GitHub 仓库（强烈建议私有）作为可信传输介质，把 `~/.copilot` 中可分享的部分（MCP server 定义、技能、agents、prompts、settings）以及可选的会话历史，在多台 devbox 之间搬运。

工具明确将"配置同步"与"会话历史同步"两条职责拆分，避免会话历史中的敏感内容在常规 `push` 中意外泄露。资料来源：[README.md:1-50]()。

## 技术栈与运行时要求

该工具以 ESM 模块形式发布（`"type": "module"`），通过 npm 全局安装：

- 运行时：Node.js >= 18.17，可执行入口 `bin/copilot-sync.js`。
- 命令行框架：[`commander`](https://www.npmjs.com/package/commander) `^12.1.0`，负责子命令与参数解析。
- 本地索引：[`better-sqlite3`](https://www.npmjs.com/package/better-sqlite3) `^11.10.0`，用于会话历史的结构化检索。
- 跨平台支持：macOS、Linux、Windows，并自带跨平台行尾的 `.gitattributes` 模板。资料来源：[package.json:1-30]()、[src/commands/onboard.js:1-30]()。

## 系统架构与数据流

整体架构围绕"用户自有 Git 仓库 + 本地 SQLite 索引 + 严格筛选"三层组成：

```mermaid
flowchart LR
  User[开发者] --> CLI[copilot-sync CLI<br/>commander]
  CLI --> Cfg[~/.copilot-sync/config.json]
  CLI --> Repo[~/.copilot-sync/repo<br/>本地托管克隆]
  CLI --> Bak[~/.copilot-sync/backups/&lt;timestamp&gt;/]
  CLI --> Src[~/.copilot<br/>skills · agents · prompts<br/>mcp-config · settings · session-state]
  CLI --> Remote[(GitHub 私有仓库<br/>transport)]
  CLI --> DB[(SQLite 会话索引<br/>better-sqlite3)]
  Src -. allow-list + deny-list .-> CLI
  Src -. secret scan .-> CLI
  Remote <--> Repo
```

主要子命令及职责：

| 子命令 | 关键职责 |
| --- | --- |
| `onboard` | 交互式收集远端 URL、分支、history mode，写入 `config.json`，并在仓库根目录写入 `.gitattributes` 和说明 README。 |
| `push` | 基于 manifest 的 allow-list 收集文件 → secret scan → 提交并推送至远端。 |
| `pull` | 从远端拉取 → 写回 `~/.copilot`，覆盖前做时间戳备份。 |
| `history push/pull` | 按 `history.mode`（`override` 或 `sync`）在本地 SQLite 索引与远端会话之间迁移。 |

资料来源：[README.md:14-130]()、[src/commands/onboard.js:1-80]()、[src/commands/push.js:1-80]()。

## 安全模型与文件筛选

为防止凭据、运行时文件被意外上传，copilot-sync 实现了多层防护：

1. **Allow-list 收集**：manifest 仅声明要同步的路径（如 `mcp-config.json`、`settings.json`、`skills/`）。
2. **全局 deny-list**：[src/manifest.js](src/manifest.js) 维护一份与 manifest 叠加的排除规则，覆盖 `auth/`、`logs/`、`shell_snapshots/`、`*.db`、`*.sqlite`、`*.log`、`node_modules/`、`.git/` 等敏感或运行时路径。
3. **Secret scan**：[src/secrets.js](src/secrets.js) 在 `push` 前对每行进行高置信度模式匹配，覆盖 GitHub PAT、GitHub fine-grained PAT、OpenAI/Anthropic key、AWS access key、Google API key、Slack token、JWT 等。
4. **原子写入与备份**：`pull` 与 `history restore` 在覆盖前先把原文件落到 `~/.copilot-sync/backups/<timestamp>/`，必要时可通过 `COPILOT_SYNC_HOME` 覆盖状态目录。资料来源：[src/manifest.js:1-80]()、[src/secrets.js:1-40]()、[README.md:95-115]()。

`history.mode` 还提供 `override`（追加式归档）与 `sync`（按最近变更时间单向同步）两种策略，并默认跳过本地活跃会话，避免污染进行中的工作。

## 会话历史索引

会话历史采用 SQLite 进行本地索引化，由 [`src/history-store.js`](src/history-store.js) 实现。核心表结构包括：

- `sessions`：会话元数据（`id`、`cwd`、`repository`、`branch`、`summary` 等）。
- `turns`：按 `turn_index` 存储用户/助手消息。
- `checkpoints`：里程碑摘要（`overview`、`history`、`work_done`、`technical_details`、`important_files`、`next_steps`）。
- `session_files` 与 `session_refs`：会话引用的文件路径与外部引用。
- `search_index`：基于 FTS5 的全文搜索虚拟表，便于跨会话检索。

写入使用 `db.transaction` 批量提交，并通过 `INSERT ... ON CONFLICT ... DO UPDATE` 与 `UNIQUE(session_id, ...)` 约束保证幂等更新。日志输出由 [`src/log.js`](src/log.js) 提供，自动识别 TTY 与 `NO_COLOR` 环境变量。资料来源：[src/history-store.js:1-120]()、[src/log.js:1-30]()。

## See Also

- [命令与参数参考](./commands.md)：onboard / push / pull / history 子命令的完整参数与退出码。
- [配置与 Manifest 自定义](./configuration.md)：详解 `~/.copilot-sync/config.json`、allow-list 与 deny-list 的合并规则。
- [常见失败模式与排错](./troubleshooting.md)：推送失败、活动会话跳过、隐私确认提示等场景的处理方式。

---

<a id='page-2'></a>

## CLI 命令与日常同步工作流

### 相关页面

相关主题：[项目概览与系统架构](#page-1), [配置文件、Allow/Deny 清单与安全模型](#page-3), [会话历史同步与两种模式](#page-4)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [README.md](https://github.com/lvxiaoxin/copilot-sync/blob/main/README.md)
- [package.json](https://github.com/lvxiaoxin/copilot-sync/blob/main/package.json)
- [bin/copilot-sync.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/bin/copilot-sync.js)
- [src/commands/onboard.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/commands/onboard.js)
- [src/commands/history.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/commands/history.js)
- [src/manifest.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/manifest.js)
- [src/secrets.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/secrets.js)
- [src/history-store.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/history-store.js)
- [src/prompt.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/prompt.js)
</details>

# CLI 命令与日常同步工作流

`copilot-sync` 是一个跨平台的 Node.js CLI 工具（包名 `@lvxiaoxin/copilot-sync`），通过一个用户自有的 GitHub 仓库在多台开发机之间同步 GitHub Copilot CLI 的可分享配置与（可选的）会话历史。该工具的核心职责是提供一组**幂等且可预览**的子命令，覆盖「首次接入」「日常配置同步」「会话历史传输」三类典型工作流，资料来源：[package.json:1-40]()。

## 命令总览与入口

工具入口声明在 `package.json` 的 `bin` 字段中，安装后可通过 `copilot-sync` 调用，对应实现为 [bin/copilot-sync.js]()。其内部使用 `commander`（`"commander": "^12.1.0"`）注册子命令，资料来源：[package.json:34-37]()。

```mermaid
flowchart LR
    A[首次接入] --> B[copilot-sync onboard]
    B --> C[写入 ~/.copilot-sync/config.json]
    C --> D[copilot-sync status]
    D --> E[copilot-sync push / pull]
    E --> F{是否同步会话?}
    F -- 否 --> G[日常配置同步]
    F -- 是 --> H[copilot-sync history push / pull]
```

## 核心配置同步命令

四个核心命令构成日常配置同步的最小闭环：

| 命令 | 主要作用 | 资料来源 |
| --- | --- | --- |
| `onboard` | 交互式配置远端仓库、分支与 history.mode，并初始化 `.gitattributes` | [src/commands/onboard.js]() |
| `status` | 查看当前远端、分支、history mode 与同步概览 | [README.md:43-60]() |
| `push` | 收集配置 → secret scan → 提交并推送 | [README.md:53-54]() |
| `pull` | 拉取远端并写入 `~/.copilot`，覆盖前备份 | [README.md:56-57]() |

### onboard：首次接入

`onboard` 是状态机式的入口：它会探测本地 `git` 是否可用，再读取 `~/.copilot-sync/config.json` 是否已存在，资料来源：[src/commands/onboard.js]()。若已配置，会询问「Reconfigure?」并允许覆盖。`onboard` 还会生成托管仓库根目录下的 `.gitattributes`，统一跨平台换行符，避免 Windows/macOS/Linux 之间出现无意义的 diff，资料来源：[src/commands/onboard.js:18-35]()。

### push 与 pull：日常循环

日常使用遵循「**先预览后执行**」原则：

```bash
copilot-sync push --dry-run   # 预览
copilot-sync push             # 实际推送
copilot-sync pull --dry-run   # 预览恢复
copilot-sync pull             # 实际恢复
```

`push` 的内部流水线为：依据 [src/manifest.js]() 的 allow-list 收集文件 → 通过 [src/secrets.js]() 的高置信 token 模式做 secret scan → 在托管仓库内做原子写入并 `git commit && git push`。`pull` 则反向：在覆盖本地文件前，将被覆盖的内容时间戳备份到 `~/.copilot-sync/backups/<timestamp>/`，并保持「只写远端存在的文件，不删除本地独有文件」的不变量，资料来源：[README.md:104-110]()。

## 历史模式与会话同步

会话历史通过独立的命令族处理，与日常配置解耦。`history` 子命令入口在 [src/commands/history.js]()，依赖 [src/history-store.js]() 提供的 SQLite 索引（基于 `better-sqlite3`，`"better-sqlite3": "^11.10.0"`）将每个会话的 turns / checkpoints / files / refs / FTS5 搜索索引物化下来，资料来源：[src/history-store.js:5-60]()。

`onboard` 阶段必须选择 `history.mode`，两种模式的行为差异如下：

| 模式 | `history push` | `history pull` | 冲突策略 |
| --- | --- | --- | --- |
| `override`（默认） | 追加式归档本机会话到远端 | 从远端恢复并覆盖本地 | 远端为准 |
| `sync` | 仅推送 `local-only` / `local-newer` | 仅拉取 `remote-only` / `remote-newer` | 会话级按 `updated_at` 较新者胜出 |

`sync` 模式以**会话 id** 为冲突单位，本地仍在活跃的会话默认跳过，需显式 `--force` 才会被覆盖，资料来源：[README.md:77-95]()。

常用参数包括：`--session <id>`（按完整 id 或唯一前缀选中单个会话）、`--since <window>`（推送侧时间窗过滤，支持 `7d` / `2w` / `1m` / `1y`）、`--dry-run`、`--yes`（跳过隐私确认）、`--force` 与 `--force-large`（绕过 100MB GitHub 限制告警），资料来源：[README.md:95-102]()。

## 交互原语与安全模型

CLI 的交互层封装在 [src/prompt.js]()：基于 `readline` 暴露 `ask` / `confirm` / `close`，并提供 `createPrompter()` 复用单例以减少多次提问时的反复开关开销，资料来源：[src/prompt.js:1-40]()。

安全方面，工具以「allow-list 收集 + hard deny-list 拦截 + secret scan + 原子写 + 时间戳备份」四道闸门兜底。deny-list 显式拒绝 `node_modules/**`、`.git/**`、`*.sqlite*`、`*.db*`、`*.log`、崩溃上下文、shell 快照、`ide/**`、`.agent-sync-meta.json` 等敏感或运行时产物，资料来源：[src/manifest.js:1-60]()。Secret scanner 在逐行匹配 GitHub PAT、`sk-` 系列密钥、AWS Access Key、Google API Key、Slack token、JWT 等高置信模式后再放行，资料来源：[src/secrets.js:1-20]()。

## See Also

- [README.md](https://github.com/lvxiaoxin/copilot-sync/blob/main/README.md) — 安装、快速开始与 FAQ
- [src/commands/onboard.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/commands/onboard.js) — 首次接入与 `.gitattributes` 生成
- [src/commands/history.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/commands/history.js) — 会话历史传输实现
- [src/history-store.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/history-store.js) — 会话索引与 FTS5 搜索
- [src/manifest.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/manifest.js) — allow/deny 清单解析
- [src/secrets.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/secrets.js) — 推送前密钥扫描

---

<a id='page-3'></a>

## 配置文件、Allow/Deny 清单与安全模型

### 相关页面

相关主题：[项目概览与系统架构](#page-1), [CLI 命令与日常同步工作流](#page-2)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/config.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/config.js)
- [src/manifest.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/manifest.js)
- [src/secrets.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/secrets.js)
- [src/collect.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/collect.js)
- [src/tree.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/tree.js)
- [src/fsutil.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/fsutil.js)
- [src/history.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/history.js)
- [src/commands/onboard.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/commands/onboard.js)
- [src/commands/push.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/commands/push.js)
- [src/log.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/log.js)
- [README.md](https://github.com/lvxiaoxin/copilot-sync/blob/main/README.md)
- [package.json](https://github.com/lvxiaoxin/copilot-sync/blob/main/package.json)
</details>

# 配置文件、Allow/Deny 清单与安全模型

## 1. 概览与设计目标

`copilot-sync` 的核心职责是把 `~/.copilot` 中**可分享**的部分（MCP 配置、技能、agents、prompts、settings）跨机器同步到一个**用户自有的 GitHub 仓库**，并把凭据、运行时状态、会话历史等**敏感内容**显式排除在外。围绕这一目标，工具在三个层面构建安全护栏：配置文件（决定要收集什么）、Allow/Deny 清单（决定如何筛选路径）以及 secret 扫描与原子写（决定是否真正落地）。

设计原则在 [README.md](https://github.com/lvxiaoxin/copilot-sync/blob/main/README.md) 中被概括为四条：

1. 配置文件使用 allow-list 收集。
2. 认证/运行时/敏感路径使用 hard deny-list 拦截。
3. 配置 push 前执行 secret scan。
4. 覆盖前做原子写入和时间戳备份。

## 2. 配置文件 `~/.copilot-sync/config.json`

运行时配置写入 `~/.copilot-sync/config.json`，并在 `copilot-sync onboard` 阶段由 [src/commands/onboard.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/commands/onboard.js) 引导生成。该命令会先通过 `ensureGitAvailable` 校验环境中的 `git`，再读取已有配置（若已 onboard 则提示 "Reconfigure?"），最后把用户输入写入配置文件中。

典型结构如下（来自 [README.md](https://github.com/lvxiaoxin/copilot-sync/blob/main/README.md)）：

```json
{
  "remote": "git@github.com:you/copilot-store.git",
  "branch": "main",
  "history": { "mode": "sync" },
  "manifest": {
    "copilot": { "include": ["mcp-config.json", "settings.json", "skills"] }
  }
}
```

关键字段含义：

| 字段 | 作用 |
| --- | --- |
| `remote` / `branch` | 远端 Git 仓库与默认分支，决定 push/pull 的目标。 |
| `history.mode` | 取值 `override`（默认）或 `sync`，控制会话历史的合并策略。 |
| `manifest.<agent>` | 每个 agent 的 allow-list 与 base 路径，会由 [src/manifest.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/manifest.js) 的 `resolveManifest` 与内置默认值合并。 |

状态目录可通过环境变量 `COPILOT_SYNC_HOME` 覆盖根路径；`~/.copilot-sync/backups/<timestamp>/` 用于 pull/restore 前的回滚备份。

## 3. Allow / Deny 清单机制

清单系统是安全模型的**核心过滤器**。它在 [src/manifest.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/manifest.js) 中以**两层 glob 数组**的形式定义：

- **`include`**（allow-list）：用户在 `manifest.<agent>.include` 中声明的子路径白名单，例如 `mcp-config.json`、`settings.json`、`skills/`、`agents/`、`prompts/`。
- **内置 deny-list**：模块顶部维护了一组**敏感路径模板**，覆盖日志、崩溃上下文、IDE 状态、临时文件、SQLite 库、个人设置以及各种备份/缓存产物。

关键的 deny 模式包括（节选自 [src/manifest.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/manifest.js)）：

| Deny 模式 | 作用 |
| --- | --- |
| `**/logs/**`、`**/log/**`、`**/*.log` | 防止日志外泄 |
| `**/crash-context/**`、`**/shell_snapshots/**`、`**/computer-use/**` | 阻止运行态/快照泄漏 |
| `**/ide/**`、`**/memories/**`、`**/restart/**` | IDE 偏好与历史 |
| `**/backups/**`、`**/.tmp/**`、`**/tmp/**`、`**/*.bak`、`**/*.backup` | 备份与临时文件 |
| `**/*.sqlite`、`**/*.sqlite-*`、`**/*.db`、`**/*.db-*` | 任何数据库及其 WAL/SHM 影子 |
| `**/installation_id`、`**/version.json`、`**/.personality_migration`、`**/.last-cleanup`、`**/stats-cache.json`、`**/vscode.session.metadata.cache.json`、`**/permissions-config.json` | 设备指纹与权限配置 |
| `**/node_modules/**`、`**/.git/**`、`**/.DS_Store`、`**/.agent-sync-meta.json` | 噪声与元数据 |

针对**会话历史**，[src/history.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/history.js) 还维护了独立的 `SENSITIVE_DENY`，覆盖 `.env`、`.env.*`、`.npmrc`、`.pypirc`、`.netrc`、`.git-credentials`、`.htpasswd`、`.dockercfg`、`credentials`、`id_rsa`/`id_dsa`/`id_ecdsa`/`id_ed25519` 以及 `*.pem`/`*.pfx`/`*.p12`/`*.ppk`，进一步锁死凭据相关的常见文件名。

`resolveManifest(userManifest)` 的合并策略是：内置 `DEFAULT_MANIFEST` 提供默认 `base` 与 `include`，用户配置在**存在且非空**时才覆盖默认值，否则保留默认 allow-list，从而避免配置错误导致**“全量打包”**。

## 4. Secret 扫描、原子写与体积护栏

即便 allow/deny 过滤生效，工具仍假设配置文件中可能夹带密钥，因此在 push 之前调用 [src/secrets.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/secrets.js) 中的扫描器。扫描器包含两类规则：

1. **高置信度 Token 形态**（逐行匹配）：GitHub 经典与 fine-grained PAT、`sk-` / `sk-ant-` 前缀的 OpenAI/Anthropic key、`AKIA*` AWS Access Key、`AIza*` Google API key、`xox[baprs]-*` Slack token，以及三段式 JWT。
2. **疑似赋值模式** `ASSIGN_RE`：匹配 `api_key|secret|token|password|auth_token|access_token|client_secret|private_key` 等键名后跟 `=` / `:` 的赋值。

扫描器通过 [src/fsutil.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/fsutil.js) 中的 `looksBinary` 跳过二进制文件，减少误报与性能开销；命中后由 [src/log.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/log.js) 抛出 `UserError`，以红色 `✗` 输出但**不带堆栈**，保证用户体验。

写入端 [src/commands/push.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/commands/push.js) 使用 `writeFileAtomic`（来自 fsutil），配合 `.agent-sync-meta.json` 元数据管理；commit 信息由主机名、平台与 ISO 时间戳构成，便于在 GitHub 端审计。pull 流程则会先把被覆盖的文件复制到 `~/.copilot-sync/backups/<timestamp>/` 再写新值，确保**覆盖可回滚**。

为避免 GitHub 拒绝 100MB 以上的文件，[src/history.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/history.js) 定义了三档体积阈值：`WARN_FILE_LIMIT = 50MB`（提示）、`HARD_FILE_LIMIT = 95MB`（拒绝）、`WARN_TOTAL = 100MB`（总量警告）。同时，活跃会话（`ACTIVE_WINDOW_MS = 10 * 60 * 1000`）默认被跳过，避免撕裂正在写入的 SQLite 副本。

## 5. 常见失败模式与排错

| 现象 | 根因 | 处理建议 |
| --- | --- | --- |
| `Push failed. Check your access to ...` | SSH key / PAT 未配置或权限不足 | 检查远端 URL 与 `~/.ssh/config`，必要时使用 HTTPS + PAT |
| `secret scan` 误报 | JSON 中含形似 token 的字符串 | 改用占位符；确属误报可使用 `--unsafe-allow`（README 不推荐） |
| `--dry-run` 之后仍写本地 | 设计上 dry-run 完全只读 | 无需操作；用真实
Error with Openai API: output new_sensitive (1027)

Please check that you have set the OPENAI_API_KEY environment variable with a valid API key.

---

<a id='page-4'></a>

## 会话历史同步与两种模式

### 相关页面

相关主题：[CLI 命令与日常同步工作流](#page-2), [配置文件、Allow/Deny 清单与安全模型](#page-3)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [README.md](https://github.com/lvxiaoxin/copilot-sync/blob/main/README.md)
- [src/manifest.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/manifest.js)
- [src/history-store.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/history-store.js)
- [src/secrets.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/secrets.js)
- [src/commands/onboard.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/commands/onboard.js)
- [src/commands/push.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/commands/push.js)
- [package.json](https://github.com/lvxiaoxin/copilot-sync/blob/main/package.json)
</details>

# 会话历史同步与两种模式

## 概述与定位

`copilot-sync` 是一个跨平台 CLI，目标是让 GitHub Copilot CLI 的可共享配置与可选的会话历史在多台开发机之间通过用户自有的 GitHub 仓库同步（[package.json:1-30]()）。其中**会话历史同步**是一个独立子系统：普通 `copilot-sync push` / `pull` 只搬运 `mcp-config.json`、`settings.json`、`skills/`、`agents/`、`prompts/` 等声明文件（[README.md]()[src/manifest.js:1-60]()），而会话历史只能通过 `copilot-sync history ...` 这一组子命令搬运——这是项目作者刻意将“配置同步”和“历史同步”分开的设计边界。

历史数据落地为本地 SQLite 数据库（依赖 `better-sqlite3 ^11.10.0`，见 [package.json:30-35]()），并带有 FTS5 全文检索表。这套数据库既是被搬运的对象（导出 / 导入 JSON），也是远端仓库中存档的索引载体（[src/history-store.js:1-40]()）。

## 数据模型与状态单元

会话历史的最小同步单位是 **session id**：每个 session 拥有自己的 `cwd`、`repository`、`host_type`、`branch`、`summary`、`created_at`、`updated_at`，并通过外键挂载 turns、checkpoints、session_files、session_refs 以及 `search_index`（FTS5）五个子表（[src/history-store.js:1-50]()）。

冲突判断规则因此落在“最近变更时间较新的一侧”——`session.updated_at` 是判定 `local-newer` / `remote-newer` 的唯一时间锚点，这一点由 README 的 `sync` 模式说明直接给出（[README.md]()）。

## 两种 history.mode

`copilot-sync onboard` 会在初始化时询问 `history.mode`，该字段写入 `~/.copilot-sync/config.json`（[src/commands/onboard.js:1-50]()）。两种模式语义如下（[README.md]()）：

| 模式 | `history push` 行为 | `history pull` 行为 | 冲突裁决 |
| --- | --- | --- | --- |
| `override`（默认） | 追加式归档本机会话到远端 | 从远端恢复到本地，覆盖前备份 | 以远端覆盖本地，不比较新旧 |
| `sync` | 仅推送 `local-only` 或 `local-newer` 会话 | 仅拉取 `remote-only` 或 `remote-newer` 会话 | 按 session id 逐条比 `updated_at`，新者胜 |

下图为 `sync` 模式在一次 push/pull 调用中的判定流程：

```mermaid
flowchart LR
  L[本地 session] -->|updated_at| C{与远端比较}
  R[远端 session] -->|updated_at| C
  C -->|本地更新| P[推送]
  C -->|远端更新| S[跳过 push]
  C -->|仅本地| P
  C -->|仅远端| SK[跳过 push]
```

`sync` 模式下，本地活跃会话默认被跳过；用户可用 `--force` 强行纳入（[README.md]()）。被替换的本地文件仍会落到 `~/.copilot-sync/backups/<timestamp>/`，这是 push/pull 共同的“安全网”（[README.md]()[src/commands/push.js:1-40]()）。

## 安全与边界

会话历史可能包含文件路径、命令输出乃至凭据，因此：

1. `src/manifest.js` 的默认 deny-list 拦截 `**/logs/**`、`**/*.sqlite`、`**/*.db`、`**/*.log`、`**/.git/**` 等敏感路径，避免被错误地纳入配置同步（[src/manifest.js:1-60]()）。
2. `src/secrets.js` 内置 GitHub PAT、OpenAI/Anthropic `sk-`、AWS `AKIA…`、Google `AIza…`、Slack `xoxb-…`、JWT 等高置信度 token 正则，以及 `api_key/secret/token/password/...` 赋值的二次匹配（[src/secrets.js:1-30]()）。
3. 任何 `push` 在提交前都会执行 secret scan；`push --unsafe-allow` 是显式旁路，需要用户主动承担风险（[README.md]()）。
4. 远端仓库应保持私有（README 在两处用 `> [!IMPORTANT]` 块强调）。

## 常用入口

历史子命令通过独立入口暴露，避免污染主配置同步的语义（[README.md]()）：

- `copilot-sync history list`：列出本地 / 远端会话并标注 `synced` / `local-only` / `remote-only`。
- `copilot-sync history push [--since <window>]`：按 `history.mode` 推送；`--since 7d` 之类的窗口只对本地侧生效。
- `copilot-sync history pull [--session <id>]`：按模式拉取，支持完整 id 或唯一前缀。
- `--yes` 跳过 push 的一次性隐私确认；`--force-large` 允许接近 GitHub 100MB 限制的体积。

## See Also

- 配置同步（allow-list / deny-list）详见 manifest 模块：[src/manifest.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/manifest.js)
- 安全扫描实现：[src/secrets.js](https://github.com/lvxiaoxin/copilot-sync/blob/main/src/secrets.js)
- 项目主文档：[README.md](https://github.com/lvxiaoxin/copilot-sync/blob/main/README.md)

---

<!-- evidence_pipeline_checked: true -->

---

## Doramagic 踩坑日志

项目：lvxiaoxin/copilot-sync

摘要：发现 6 个潜在踩坑项，其中 0 个为 high/blocking；最高优先级：能力坑 - 能力判断依赖假设。

## 1. 能力坑 · 能力判断依赖假设

- 严重度：medium
- 证据强度：source_linked
- 发现：README/documentation is current enough for a first validation pass.
- 对用户的影响：假设不成立时，用户拿不到承诺的能力。
- 证据：capability.assumptions | https://github.com/lvxiaoxin/copilot-sync | README/documentation is current enough for a first validation pass.

## 2. 维护坑 · 维护活跃度未知

- 严重度：medium
- 证据强度：source_linked
- 发现：未记录 last_activity_observed。
- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。
- 证据：evidence.maintainer_signals | https://github.com/lvxiaoxin/copilot-sync | last_activity_observed missing

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 证据：downstream_validation.risk_items | https://github.com/lvxiaoxin/copilot-sync | no_demo; severity=medium

## 4. 安全/权限坑 · 存在评分风险

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 对用户的影响：风险会影响是否适合普通用户安装。
- 证据：risks.scoring_risks | https://github.com/lvxiaoxin/copilot-sync | no_demo; severity=medium

## 5. 维护坑 · issue/PR 响应质量未知

- 严重度：low
- 证据强度：source_linked
- 发现：issue_or_pr_quality=unknown。
- 对用户的影响：用户无法判断遇到问题后是否有人维护。
- 证据：evidence.maintainer_signals | https://github.com/lvxiaoxin/copilot-sync | issue_or_pr_quality=unknown

## 6. 维护坑 · 发布节奏不明确

- 严重度：low
- 证据强度：source_linked
- 发现：release_recency=unknown。
- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。
- 证据：evidence.maintainer_signals | https://github.com/lvxiaoxin/copilot-sync | release_recency=unknown

<!-- canonical_name: lvxiaoxin/copilot-sync; human_manual_source: deepwiki_human_wiki -->
