# Portable Toolkit

`portable-toolkit` 是一组便携式命令行工具，面向日常开发、DevOps 和 AI 客户端配置同步场景。

当前包含以下工具：

| 工具 | 说明 |
| --- | --- |
| `git_commit_generator` | 基于暂存区 diff 调用 AI API，生成 Conventional Commits 风格的提交信息 |
| `mcp_sync` | 将统一的 `mcpServers.json` 同步到多个 AI 客户端的全局 MCP 配置 |
| `file_cipher` | 使用 AES-128-GCM 对文件进行加密和解密 |
| `get_ip_info` | 请求 `https://ipinfo.io/json` 并输出当前公网 IP 信息 |

## 环境要求

- Rust 2021 工具链
- Git，`git_commit_generator` 需要用它读取暂存区变更
- AI API 配置，仅 `git_commit_generator` 需要
- `cargo-zigbuild`、MinGW 和对应 Rust target，仅跨平台构建需要

## 快速开始

```bash
# 构建所有二进制工具
cargo build

# 构建 release 版本
cargo build --release

# 运行默认工具 git_commit_generator
cargo run

# 运行指定工具
cargo run --bin mcp_sync -- --help
cargo run --bin file_cipher -- --help
cargo run --bin get_ip_info
```

release 产物位于 `target/release/`。

## git_commit_generator

`git_commit_generator` 会读取当前 Git 仓库的暂存区变更：

```bash
git diff --cached
```

然后调用配置的 AI API，生成提交信息。默认只输出可执行的 `git commit -m "..."` 命令；使用 `--auto` 时会直接执行提交。

### 配置

在项目根目录创建 `.env`：

```dotenv
AI_API_KEY="your_api_key"
AI_API_URL="https://api.example.com/v1/chat/completions"
AI_MODEL="model-name"
```

| 变量 | 说明 |
| --- | --- |
| `AI_API_KEY` | AI 服务 API Key |
| `AI_API_URL` | AI API 请求地址 |
| `AI_MODEL` | 请求体中的模型名称 |

### 用法

```bash
# 1. 暂存变更
git add .

# 2. 生成 commit 命令
cargo run --bin git_commit_generator

# 3. 自动生成并执行 git commit
cargo run --bin git_commit_generator -- --auto

# 4. 设置 AI API 超时时间，单位为毫秒
cargo run --bin git_commit_generator -- --timeout 60000
```

也可以直接运行 release 二进制：

```bash
./target/release/git_commit_generator
./target/release/git_commit_generator --auto
```

## mcp_sync

`mcp_sync` 会将单一来源的 `mcpServers.json` 同步到多个 AI 客户端的全局配置文件。默认来源：

```text
~/data/config/ai_conf/mcpServers.json
```

### 支持的客户端

| Client | 配置文件 | 格式 |
| --- | --- | --- |
| `claude` | `~/.claude.json` | JSON |
| `codex` | `~/.codex/config.toml` | TOML |
| `copilot` | `~/.copilot/mcp-config.json` | JSON |
| `gemini` | `~/.gemini/settings.json` | JSON |
| `cursor` | `~/.cursor/mcp.json` | JSON |

同步时会保留目标配置文件中的其他字段，只替换 MCP 配置段：

- JSON 客户端替换 `mcpServers`
- Codex TOML 配置替换 `mcp_servers`

### 用法

```bash
# 同步到所有支持的客户端
cargo run --bin mcp_sync

# 只同步到指定客户端
cargo run --bin mcp_sync -- --clients cursor
cargo run --bin mcp_sync -- --clients claude,codex,cursor

# 使用自定义来源配置
cargo run --bin mcp_sync -- --config /path/to/mcpServers.json
```

构建后运行：

```bash
mcp_sync
mcp_sync --clients cursor
mcp_sync --config /path/to/mcpServers.json
```

## file_cipher

`file_cipher` 使用 AES-128-GCM 加密和解密文件。密钥必须严格为 16 字节。

```bash
# 加密文件
cargo run --bin file_cipher -- encrypt \
  --input plain.txt \
  --output cipher.bin \
  --key 1234567890123456

# 解密文件
cargo run --bin file_cipher -- decrypt \
  --input cipher.bin \
  --output restored.txt \
  --key 1234567890123456
```

加密输出格式：

```text
12 字节 nonce + 密文 + GCM tag
```

## get_ip_info

`get_ip_info` 会请求 `https://ipinfo.io/json` 并打印响应内容。

```bash
cargo run --bin get_ip_info

# release 二进制
./target/release/get_ip_info
```

## 质量检查

```bash
# 格式化代码
cargo fmt

# 检查格式
cargo fmt --all -- --check

# 运行 Clippy
cargo clippy --all-targets --all-features -- -D warnings

# 运行测试
cargo test --all --all-features

# 构建文档
RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --all-features
```

## 跨平台构建

项目提供 `scripts/install.sh` 用于本地和跨平台构建。默认只构建当前平台，并安装到：

```text
~/data/bin
```

```bash
# 构建当前平台
cd scripts
./install.sh

# 构建所有支持平台
BUILD_MODE=all ./install.sh

# 强制使用 cargo-zigbuild
BUILD_CMD=zigbuild ./install.sh

# Debug 模式
DEBUG=true ./install.sh
```

支持平台：

- `x86_64-apple-darwin`
- `aarch64-apple-darwin`
- `x86_64-unknown-linux-gnu`
- `aarch64-unknown-linux-gnu`
- `x86_64-pc-windows-gnu`

跨平台构建产物会复制到：

```text
target/releases/{platform}/
```

更多说明见 [scripts/BUILD.md](scripts/BUILD.md)。

## 项目结构

```text
src/
├── bin/
│   ├── file_cipher.rs
│   ├── get_ip_info.rs
│   ├── git_commit_generator.rs
│   └── mcp_sync.rs
├── cipher.rs
├── lib.rs
├── mcp_sync/
└── model/
```

## 注意事项

- `.env` 包含敏感信息，已被 `.gitignore` 忽略，不要提交。
- `git_commit_generator` 必须在 Git 仓库内运行，并且需要有暂存区变更。
- `file_cipher` 的密钥长度必须严格为 16 字节。
- Podman 不支持短镜像名；如后续添加容器相关命令，请使用完整镜像名。
