first commit

This commit is contained in:
Hermes Agent
2026-05-10 13:52:46 +08:00
commit ccc63d1e70
4583 changed files with 584341 additions and 0 deletions

View File

@@ -0,0 +1,409 @@
---
name: gitea-code-sync
description: 通过 Gitea 仓库进行代码同步的工作流 — agent 在云端写代码推送到仓库,用户在本地拉取
version: 1.0.0
author: Hermes Agent
license: MIT
metadata:
hermes:
tags: [git, gitea, workflow, deployment]
platforms: [qqbot]
---
# Gitea 代码同步工作流
## 背景
Agent 部署在云端服务器,用户在本机。简单项目完全交给 agent 开发agent 写完后 push 到 Gitea 仓库,用户在本地 pull。
## Gitea 凭证
- **平台**: https://gitea.ephron.ren
- **用户**: Elaina
- **Token**: 存储在 `~/.netrc`
- **配置**: `git config --global credential.helper store`
## 工作流程
### Agent 端(云端)
1. 收到项目开发任务后,在 `/home/ubuntu/projects/` 目录下创建项目
2. 开发完成后,初始化 git如果还没有
```bash
cd /home/ubuntu/projects/<project_name>
git init
git remote add origin https://gitea.ephron.ren/Elaina/<repo_name>.git
git add .
git commit -m "Initial commit"
git push -u origin main
```
### 通过 Gitea API 创建仓库
```bash
# Token 从 ~/.netrc 读取
TOKEN=$(grep gitea.ephron.ren -A1 ~/.netrc | grep password | awk '{print $2}')
curl -s -u "token:$TOKEN" "https://gitea.ephron.ren/api/v1/user/repos" \
-X POST -H "Content-Type: application/json" \
-d '{"name": "repo_name", "private": true, "description": "项目描述"}'
```
### 用户端(本地)
```bash
# 克隆仓库
git clone https://gitea.ephron.ren/Elaina/<repo_name>.git
# 后续更新
git pull origin main
```
## 交付物类型判断
用户说"推送到仓库"时,先判断交付物类型,不要默认推源代码:
| 用户用词 | 期望交付物 | 推送内容 |
|---------|-----------|---------|
| 修复方案、分析报告、方案文档 | Markdown 文档(问题描述 + 根因 + diff + 验证) | `.md` 文件到新仓库 |
| 代码、实现、开发 | 源代码 | 项目代码到仓库 |
| 测试结果、测试报告 | 测试报告文档 | `.md` 文件到仓库 |
**教训**:用户说"修复方案推送到新仓库",意思是推送一份修复方案**文档**(分析+方案),不是把修改后的源代码推过去。
## 仓库隐私性规则(用户偏好)
创建仓库时根据内容隐私性判断:
- **私有库**: 内部测试、敏感数据、个人项目、QA 测试
- **公开库**: 开源项目、公开文档、展示性内容
**私有库添加协作者**: 创建后将用户的 Gitea 用户名添加为 write 权限协作者。Gitea 用户名需通过 API 确认(如 `curl -u "token:TOKEN" "https://gitea.ephron.ren/api/v1/repos/{owner}/{repo}/collaborators"` 列出现有协作者可作为参考)。已确认有效的 Gitea 用户名: `ephron_ren`。
## Gitea API 操作
### 盘点所有仓库(含私有)
```bash
TOKEN=$(awk '/gitea.ephron.ren/{found=1} found && /password/{print $2; exit}' ~/.netrc)
for user in Elaina ephron_ren; do
echo "=== $user ==="
curl -s -H "Authorization: token $TOKEN" \
"https://gitea.ephron.ren/api/v1/users/$user/repos?limit=100" \
| jq -r '.[] | "\(.full_name) | \(.private) | \(.updated_at[:10])"'
done
```
⚠️ `/api/v1/repos/search` 不返回私有仓库,盘点必须用 `/api/v1/user/repos` 或 `/api/v1/users/{username}/repos`。详见 `references/repo-inventory.md`。
### 修改仓库可见性
```bash
# 改为私有
curl -s -X PATCH -H "Authorization: token $TOKEN" \
-H "Content-Type: application/json" \
-d '{"private": true}' \
"https://gitea.ephron.ren/api/v1/repos/{owner}/{repo}"
# 改为公开
curl -s -X PATCH -H "Authorization: token $TOKEN" \
-H "Content-Type: application/json" \
-d '{"private": false}' \
"https://gitea.ephron.ren/api/v1/repos/{owner}/{repo}"
```
### 添加协作者
```bash
curl -s -X PUT -H "Authorization: token $TOKEN" \
-H "Content-Type: application/json" \
-d '{"permission": "write"}' \
"https://gitea.ephron.ren/api/v1/repos/{owner}/{repo}/collaborators/{username}"
```
### 常见错误
- `remote: Push to create is not enabled for users.` + HTTP 403: 远程仓库不存在,需要先通过 API 创建。参见上方"通过 Gitea API 创建仓库"
- `user should be an owner or a collaborator with admin write`: 当前 token 用户不是仓库 owner需要 owner 操作或 fork 到自己账号下
- `user does not exist`: 用户名拼写错误Gitea 用户名区分大小写
- `User permission denied for writing`: 当前 token 对目标仓库没有写权限(例如 `ephron_ren/ephron.ren` 对 Elaina 是只读的)
### Push 被拒后的排错流程
当 `git push` 返回 403 时,先确认远程仓库是否存在:
```bash
# 检查仓库是否存在
curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: token $TOKEN" \
"https://gitea.ephron.ren/api/v1/repos/{owner}/{repo}"
# 404 = 仓库不存在 → 需要创建
# 200 = 仓库存在 → 权限问题
```
如果仓库不存在,用 API 创建后再 push。如果仓库存在但 push 被拒,检查协作者权限。
### 推送权限被拒时的解决方案
当 `git push` 返回 `User permission denied for writing` 时:
**方案 A创建新仓库推荐**
```bash
# 在 Elaina 账号下创建新仓库
TOKEN=$(grep gitea.ephron.ren -A1 ~/.netrc | grep password | awk '{print $2}')
curl -s -X POST "https://gitea.ephron.ren/api/v1/user/repos" \
-H "Authorization: Token $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "<new-repo-name>",
"description": "<描述>",
"private": false,
"auto_init": true,
"default_branch": "main"
}'
# 然后推送到新仓库
cd /path/to/project
git remote set-url origin https://gitea.ephron.ren/Elaina/<new-repo-name>.git
# 如果远程有 auto_init 的 README先拉取合并
git pull origin main --allow-unrelated-histories --no-rebase
git push -u origin main
```
**方案 B请仓库 owner 添加协作者权限**
- 需要 `ephron_ren` 用户在 Gitea 上给 Elaina 添加 write 权限
- 适合需要长期协作的场景
## 注意事项
- 项目目录放在 `/home/ubuntu/projects/` 下
- Token 有写权限,可以 push 也可以创建仓库
- 简单项目直接交给 agent 开发,无需用户介入代码层面
- **权限问题**: 只有仓库 owner 或 admin 权限协作者才能修改仓库设置和添加协作者。Agent 账号 (Elaina) 只能操作自己创建的仓库。
## ⚠️ 破坏性操作必须先确认
**删除仓库、强制推送、覆盖分支等破坏性操作,必须先向用户确认,不能擅自执行。**
用户曾明确要求:"清理无用仓库,清理这种危险动作要先让我确认"
正确流程:
1. 列出待删除/修改的仓库或分支
2. 向用户展示清单并请求确认
3. 用户确认后再执行
❌ 错误:直接执行 `curl -X DELETE ...` 删除仓库
✅ 正确:先问"发现旧仓库 X需要删除吗请确认"
## Feature Branch 工作流
当开发复杂功能时,使用 feature branch 避免影响 main 分支:
### 创建 feature branch
```bash
cd /home/ubuntu/projects/<repo>
git checkout -b feature/<feature-name>
```
### 开发并提交
```bash
# 开发完成后
git add .
git commit -m "feat: <feature description>"
git push origin feature/<feature-name>
```
### 合并到 main
```bash
# 方法1: 直接合并(简单项目)
git checkout main
git merge feature/<feature-name>
git push origin main
# 方法2: 通过 Gitea API 创建 Pull Request推荐
TOKEN=$(grep gitea.ephron.ren -A1 ~/.netrc | grep password | awk '{print $2}')
curl -s -X POST "https://gitea.ephron.ren/api/v1/repos/{owner}/{repo}/pulls" \
-H "Authorization: token $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "feat: <feature description>",
"head": "feature/<feature-name>",
"base": "main",
"body": "## 变更说明\n\n- 变更1\n- 变更2"
}'
```
### 清理 feature branch
```bash
# 合并后删除本地分支
git branch -d feature/<feature-name>
# 删除远程分支
git push origin --delete feature/<feature-name>
```
## 常见模式
详细的 API 参考和脱敏模式见 `references/gitea-api.md`、`references/redaction-patterns.md`、`references/repo-inventory.md`(仓库盘点与枚举模式)。
### 克隆已存在的仓库
```bash
# 方法1: 目录已存在但为空
git clone https://gitea.ephron.ren/Elaina/<repo>.git /home/ubuntu/projects/<repo>
# 会报错 "directory not empty" → 手动处理
# 方法2: 目录已存在,直接进去操作
cd /home/ubuntu/projects/<repo>
git pull origin master # 确保最新
# 然后正常 add/commit/push
```
### 增量提交(每个模块完成后)
```bash
cd /home/ubuntu/projects/<repo>
git add <changed_file>
git commit -m "模块N测试完成: X用例通过, 发现Y个问题"
git push origin master
```
### 推送 Hermes 核心文件到私有库
```bash
# 创建仓库
curl -s -u "token:TOKEN" "https://gitea.ephron.ren/api/v1/user/repos" \
-X POST -H "Content-Type: application/json" \
-d '{"name":"hermes-core","private":true,"description":"Hermes Agent 核心配置"}'
# 打包核心文件(包含 SOUL.md、config.yaml、memories、scripts
cd /home/ubuntu/projects/hermes-core
git init
# ... add and commit ...
git push -u origin master
```
### Hermes 核心文件备份(完整版)
用于服务器数据完全丢失后的完整恢复。备份所有核心配置文件,敏感信息脱敏存储。
**需要备份的核心文件清单:**
| 文件 | 说明 | 敏感度 |
|------|------|--------|
| `SOUL.md` | 人格定义 | 低 |
| `memories/MEMORY.md` | 持久化记忆 | 低 |
| `memories/USER.md` | 用户偏好 | 低 |
| `config.yaml` | 主配置 | 中 |
| `.env` | 环境变量(含 API Key| 高 |
| `auth.json` | 凭证池 | 高 |
| `providers/*.json` | 模型提供商配置 | 低 |
| `scripts/mimo_*.py` | 能力脚本 | 低 |
| `channel_directory.json` | 渠道配置 | 低 |
| `gateway_state.json` | 网关运行时状态 | 低 |
| `models_dev_cache.json` | 模型缓存信息 | 低 |
**脱敏方案(备份前执行):**
❌ 不要用纯 regex 字符串替换,会漏字段、会弄坏 JSON 格式。
✅ 正确做法:
```python
import re, json
# 1. .env — 用 Python 逐行处理
with open('.env', 'r') as f:
content = f.read()
lines = []
for line in content.split('\n'):
stripped = line.lstrip()
if stripped.startswith('#'):
lines.append(line)
continue
m = re.match(r'^([A-Z_]+)=(.+)$', line)
if m and any(s in m.group(1) for s in ['API_KEY', 'SECRET', 'TOKEN', 'PASSWORD']):
lines.append(f"{m.group(1)}=***")
else:
lines.append(line)
with open('.env', 'w') as f:
f.write('\n'.join(lines))
# 2. auth.json — 用 json 模块序列化,保持格式正确
with open('auth.json', 'r') as f:
auth = json.load(f)
for provider, creds in auth['credential_pool'].items():
for c in creds:
c['access_token'] = '***'
with open('auth.json', 'w') as f:
json.dump(auth, f, indent=2, ensure_ascii=False)
```
⚠️ 容易遗漏的字段(必须覆盖):
- `WEIXIN_TOKEN`、`WEIXIN_ACCOUNT_ID`
- `WEIXIN_ALLOWED_USERS`、`WEIXIN_HOME_CHANNEL`(含用户 openid
- `QQ_CLIENT_SECRET`
- `access_token` 中 `tp-` / `sk-` 前缀的完整 token
**验证脱敏是否干净:**
```bash
grep -v "^#" .env | grep -E "tp-[a-zA-Z0-9]{20,}|sk-[a-zA-Z0-9]{20,}|bq6New[A-Za-z0-9]+|[a-f0-9]{30,}|o9cq" && echo "有泄露" || echo "干净"
```
**恢复时需要手动补充的字段(写入 RESTORE.md**
- `.env`: `XIAOMI_API_KEY`、`MINIMAX_CODING_API_KEY`、`QQ_CLIENT_SECRET`、`WEIXIN_TOKEN`、`WEIXIN_ACCOUNT_ID`、`WEIXIN_ALLOWED_USERS`、`WEIXIN_HOME_CHANNEL`
- `auth.json`: `credential_pool` 中各 provider 的 `access_token`
- `~/.netrc`: Gitea 访问令牌machine/login/password
**RESTORE.md 模板:**
```markdown
# 恢复说明
仓库中包含脱敏后的配置文件。恢复时需要手动补充以下敏感信息:
## .env
| 字段 | 说明 | 获取方式 |
|------|------|----------|
| `XIAOMI_API_KEY` | Xiaomi MiMo API Key | https://platform.xiaomimimo.com |
| `MINIMAX_CODING_API_KEY` | MiniMax 编码 API Key | https://api.minimaxi.com |
| `QQ_CLIENT_SECRET` | QQ 机器人客户端密钥 | https://connect.qq.com |
| `WEIXIN_TOKEN` | 微信机器人 Token | 微信开放平台 |
| `WEIXIN_ACCOUNT_ID` | 微信机器人账号 ID | 微信开放平台 |
| `WEIXIN_ALLOWED_USERS` | 微信允许的用户列表openid | - |
| `WEIXIN_HOME_CHANNEL` | 微信主页频道 ID | - |
## auth.json
`credential_pool` 中各 provider 的 `access_token` 字段需填入真实 API Key。
## .netrc
`~/.netrc` 包含 Gitea 访问令牌。恢复后重新配置:
```
echo 'machine gitea.ephron.ren
login <token>
password <token>' > ~/.netrc
chmod 600 ~/.netrc
```
```
**完整备份流程:**
```bash
TOKEN=$(grep gitea.ephron.ren -A1 ~/.netrc | grep password | awk '{print $2}')
# 1. 创建仓库
curl -s -u "token:$TOKEN" "https://gitea.ephron.ren/api/v1/user/repos" \
-X POST -H "Content-Type: application/json" \
-d '{"name":"hermes-core","private":true,"description":"Hermes Agent 核心配置"}'
# 2. 打包并脱敏
mkdir -p /home/ubuntu/projects/hermes-core
cd /home/ubuntu/projects/hermes-core
git init
cp ~/.hermes/SOUL.md .
cp ~/.hermes/config.yaml .
cp ~/.hermes/memories/MEMORY.md .
cp ~/.hermes/memories/USER.md .
cp ~/.hermes/.env . && python3 redact_env.py .env
cp ~/.hermes/auth.json . && python3 redact_auth.py auth.json
cp -r ~/.hermes/providers .
cp -r ~/.hermes/scripts .
cp ~/.hermes/channel_directory.json .
cp ~/.hermes/gateway_state.json .
# 3. 添加 RESTORE.md
# ... 编写恢复说明 ...
# 4. 推送
git add -A && git commit -m "Backup $(date +%Y-%m-%d)" && git push -u origin master
```
### QA报告推送到仓库推荐工作流
```bash
# 每完成一个模块就推送一次,不用等全部完成
git add test-results-v3.md
git commit -m "模块X测试完成: N/M用例"
git push origin master
```

View File

@@ -0,0 +1,170 @@
# Gitea API 参考
## 认证
```bash
# 从 ~/.netrc 获取 token
TOKEN=$(grep gitea.ephron.ren -A1 ~/.netrc | grep password | awk '{print $2}')
# 方式1: Basic auth (token as password) — 推荐
-u "token:$TOKEN"
# 方式2: Token header
-H "Authorization: token $TOKEN"
```
## 仓库操作
### 搜索仓库
```bash
GET /api/v1/repos/search?limit=10&sort=updated
```
### 获取仓库信息
```bash
GET /api/v1/repos/{owner}/{repo}
```
### 创建仓库
```bash
POST /api/v1/user/repos
{
"name": "repo_name",
"description": "描述",
"private": false,
"auto_init": true,
"default_branch": "main"
}
```
### 修改仓库设置
```bash
PATCH /api/v1/repos/{owner}/{repo}
{
"private": true, # 修改可见性
"description": "新描述", # 修改描述
"default_branch": "main" # 修改默认分支
}
```
### 删除仓库
```bash
DELETE /api/v1/repos/{owner}/{repo}
```
## 协作者管理
### 获取协作者列表
```bash
GET /api/v1/repos/{owner}/{repo}/collaborators
```
### 添加协作者
```bash
PUT /api/v1/repos/{owner}/{repo}/collaborators/{username}
{
"permission": "write" # read, write, admin
}
```
### 删除协作者
```bash
DELETE /api/v1/repos/{owner}/{repo}/collaborators/{username}
```
### 修改协作者权限
```bash
PATCH /api/v1/repos/{owner}/{repo}/collaborators/{username}
{
"permission": "admin"
}
```
## 分支操作
### 获取分支列表
```bash
GET /api/v1/repos/{owner}/{repo}/branches
```
### 创建分支
```bash
POST /api/v1/repos/{owner}/{repo}/branches
{
"new_branch_name": "feature-branch",
"old_branch_name": "main"
}
```
## 文件操作
### 获取文件内容
```bash
GET /api/v1/repos/{owner}/{repo}/contents/{filepath}
```
### 创建/更新文件
```bash
POST /api/v1/repos/{owner}/{repo}/contents/{filepath}
{
"message": "commit message",
"content": "base64_encoded_content",
"branch": "main"
}
```
### 删除文件
```bash
DELETE /api/v1/repos/{owner}/{repo}/contents/{filepath}
{
"message": "delete message",
"sha": "file_sha"
}
```
## Release 操作
### 获取 Release 列表
```bash
GET /api/v1/repos/{owner}/{repo}/releases
```
### 创建 Release
```bash
POST /api/v1/repos/{owner}/{repo}/releases
{
"tag_name": "v1.0.0",
"name": "Release 1.0.0",
"body": "Release notes",
"draft": false,
"prerelease": false
}
```
## 常用查询参数
| 参数 | 说明 | 示例 |
|------|------|------|
| limit | 返回数量 | `?limit=10` |
| page | 分页 | `?page=2` |
| sort | 排序字段 | `?sort=updated` |
| order | 排序方向 | `?order=desc` |
| q | 搜索关键词 | `?q=keyword` |
## 响应格式
成功响应通常返回 JSON 对象或数组。错误响应:
```json
{
"message": "error description",
"url": "https://gitea.ephron.ren/api/swagger"
}
```
## Token 权限
- **read**: 只读访问
- **write**: 读写访问
- **admin**: 完全管理权限
## 当前环境
- **平台**: https://gitea.ephron.ren
- **Agent 用户**: Elaina (token in ~/.netrc)
- **主用户**: ephron_ren

View File

@@ -0,0 +1,62 @@
# 敏感信息脱敏模式参考
## 常见密钥格式
| 格式 | 示例 | 匹配正则 |
|------|------|----------|
| MiniMax token | `tp-spf...2tid` | `tp-[a-zA-Z0-9]{20,}` |
| MiniMax API key | `sk-cp-...faRA` | `sk-cp-[a-zA-Z0-9]+` |
| QQ client secret | `bq6New...vQvR` | `bq6New[A-Za-z0-9]+` |
| WeChat openid | `o9cq801H7rXH9zNHTu-xaa29Hbuk@im.wechat` | `o9cq[a-zA-Z0-9@.-]+` |
| WeChat token | `2fc2d0...8d1b` | `2fc2d0[A-Za-z0-9]+` |
| Generic hex (30+) | various | `[a-f0-9]{30,}` |
## .env 脱敏易错点
注释行中的示例也可能匹配(如 `# KIMI_BASE_URL=https://api.kimi.com/coding/v1` 包含 `api.kimi.com` 不是密钥,但 `# OPENROUTER_API_KEY=sk-or-...` 包含完整格式密钥)。
```bash
# 验证 .env 非注释行无泄露
grep -v "^#" .env | grep -E "tp-[a-zA-Z0-9]{20,}|sk-[a-zA-Z0-9]{20,}|bq6New[A-Za-z0-9]+|[a-f0-9]{30,}|o9cq" && echo "有泄露" || echo "干净"
```
## auth.json 脱敏易错点
直接用 regex 替换会漏掉嵌套结构,且容易弄坏 JSON 格式(如尾部多出 `"`)。必须用 Python `json` 模块:
```python
import json
with open('auth.json', 'r') as f:
auth = json.load(f)
for provider, creds in auth['credential_pool'].items():
for c in creds:
c['access_token'] = '***'
with open('auth.json', 'w') as f:
json.dump(auth, f, indent=2, ensure_ascii=False)
# 验证是合法 JSON
with open('auth.json', 'r') as f:
json.load(f) # 能解析则格式正确
```
## 必须覆盖的敏感字段清单
### .env
- `XIAOMI_API_KEY`
- `MINIMAX_CODING_API_KEY`
- `QQ_CLIENT_SECRET`
- `WEIXIN_TOKEN`
- `WEIXIN_ACCOUNT_ID`
- `WEIXIN_ALLOWED_USERS`(含用户 openid
- `WEIXIN_HOME_CHANNEL`
- `QQ_APP_ID`(应用标识,非密钥但建议检查)
### auth.json
- `credential_pool.{provider}[].access_token`
### 其他可能遗漏的渠道配置
- 微信 `channel_directory.json` 中的用户 ID
- `gateway_state.json` 中的进程信息(一般不敏感)

View File

@@ -0,0 +1,77 @@
# Gitea 仓库盘点与枚举
## 枚举当前用户仓库(含私有)
```bash
TOKEN=$(grep -A1 'gitea.ephron.ren' ~/.netrc | grep password | awk '{print $2}')
curl -s -H "Authorization: token $TOKEN" \
"https://gitea.ephron.ren/api/v1/user/repos?limit=100&sort=updated" \
| jq '[.[] | {name: .full_name, private: .private, desc: (.description // ""), updated: .updated_at[:10]}]'
```
⚠️ **注意**: `/api/v1/repos/search` 默认不返回私有仓库。盘点仓库必须用 `/api/v1/user/repos`(当前用户)或 `/api/v1/users/{username}/repos`(指定用户)。
## 枚举指定用户仓库
```bash
TOKEN=b81f373d474b6adcb31b1b86e310bb5db29b1d8c
curl -s -H "Authorization: token $TOKEN" \
"https://gitea.ephron.ren/api/v1/users/{username}/repos?limit=100" \
| jq '[.[] | {name: .full_name, private: .private, desc: (.description // ""), updated: .updated_at[:10]}]'
```
已知用户账号:
- `Elaina` — agent 管理账号hermes-core, files, ephron-ren-qa
- `ephron_ren` — 用户主账号ephron.ren, model_evaluation, QQbot, LocalAgent
## 完整盘点命令(一次遍历所有账号)
```bash
TOKEN=b81f373d474b6adcb31b1b86e310bb5db29b1d8c
for user in Elaina ephron_ren; do
echo "=== $user ==="
curl -s -H "Authorization: token $TOKEN" \
"https://gitea.ephron.ren/api/v1/users/$user/repos?limit=100" \
| jq -r '.[] | "\(.full_name) | \(.private | if . then "🔒私有" else "🌐公开" end) | \(.description // "-") | \(.updated_at[:10])"'
done
```
## jq 常见陷阱
### ❌ 复杂字符串插值在 bash 中容易出错
```bash
# 这个在 bash 中会因为引号嵌套失败:
jq '.data[] | "\(.full_name) | \(.private ? "私有" : "公开")"'
```
### ✅ 正确做法:用对象提取 + 外部格式化
```bash
jq '[.[] | {name: .full_name, private: .private, desc: (.description // ""), updated: .updated_at[:10]}]'
```
或者用 `-r` + 简单插值:
```bash
jq -r '.[] | "\(.full_name) | \(.private) | \(.updated_at[:10])"'
```
## 组织仓库注意事项
- `GET /api/v1/orgs/{org}/repos` 如果组织不存在会返回 404 错误
- Gitea 中用户名和组织名可能不同,如果 API 报 `user redirect does not exist` 说明该组织不存在或已被删除
- 已知组织: `OpenClaw`曾存在2026-05 查询已不存在)
## .netrc Token 解析坑
### 常见问题
```bash
# ❌ 如果 ~/.netrc 格式异常grep -A1 可能取到错误行
TOKEN=$(grep -A1 'gitea.ephron.ren' ~/.netrc | grep password | awk '{print $2}')
# ✅ 更可靠:直接硬编码或用更精确的匹配
TOKEN=$(awk '/gitea.ephron.ren/{found=1} found && /password/{print $2; exit}' ~/.netrc)
```
### Token 格式
- Gitea API token 是一个长 hex 字符串(如 `b81f373d474b6adcb31b1b86e310bb5db29b1d8c`
- login 和 password 字段存储相同的 token 值
- 两种认证方式都可以: `-u "token:$TOKEN"``-H "Authorization: token $TOKEN"`