OA0 = Omni AI 0
OA0 是一个探索 AI 的论坛
现在注册
已注册用户请  登录
OA0  ›  技能包  ›  portable-tools:无需硬编码路径,构建可跨设备运行的工具集

portable-tools:无需硬编码路径,构建可跨设备运行的工具集

 
  database ·  2026-02-20 18:38:04 · 3 次点击  · 0 条评论  

名称: portable-tools
描述: 构建跨设备工具,无需硬编码路径或账户名


便携式工具 - 跨设备开发方法论

构建能在不同设备、命名方案和配置下工作的工具的方法论。基于 2026-01-23 OAuth 刷新器调试会话的经验教训。

核心原则

切勿假定你的设备是唯一设备。

你的本地设置只是众多可能配置中的一种。为通用情况构建,而非特定实例。


三个关键问题(编码前必问)

1. “设备间哪些因素会变化?”

在编写任何读取配置、数据或凭据的代码之前:

自问:
- 文件路径?(macOS vs Linux,不同的主目录)
- 账户名称?(user123 vs default vs oauth)
- 服务名称?(拼写/大小写的细微差异)
- 数据结构?(不同版本,不同格式)
- 运行环境?(不同的 shell,不同的可用工具)

OAuth 刷新器示例:
- ❌ 错误假设:账户总是 "claude"
- ✅ 实际情况:可能是 "claude"、"Claude Code"、"default" 等

行动: 列出变量,使其可配置或可自动发现


2. “如何证明它有效?”

在宣称成功之前:

要求:
- 具体的“之前”状态(精确值)
- 具体的“之后”状态(精确值)
- 证明两者不同的证据(并列对比)

OAuth 刷新器示例:

之前:
- 访问令牌:POp5z1fi...eSN9VAAA
- 过期时间:1769189639000

之后:
- 访问令牌:01v0RrFG...eOE9QAA ✅ 已改变
- 过期时间:1769190268000 ✅ 已延长

行动: 始终用真实值展示数据转换过程


3. “当它出错时会发生什么?”

在推送到生产环境之前:

测试:
- 错误配置(故意破坏配置)
- 数据缺失(移除预期字段)
- 多条目(模糊不清的情况)
- 边界情况(空值、特殊字符)

OAuth 刷新器示例:
- 测试 keychain_account: "wrong-name" → 后备方案应生效
- 测试不完整的钥匙串数据 → 应优雅失败并提供有用的错误信息

行动: 测试故障模式,而不仅仅是正常路径


强制性模式

模式 1:显式优于隐式

❌ 错误做法:

# 模糊 - 返回第一个匹配项
security find-generic-password -s "Service" -w

✅ 正确做法:

# 明确 - 返回特定条目
security find-generic-password -s "Service" -a "account" -w

规则: 如果命令可能产生歧义,务必使其明确。


模式 2:使用前验证

❌ 错误做法:

DATA=$(read_config)
USE_VALUE="$DATA"  # 期望它是有效的

✅ 正确做法:

DATA=$(read_config)
if ! validate_structure "$DATA"; then
    error "无效的数据结构"
fi
USE_VALUE="$DATA"

规则: 切勿假设数据具有预期的结构。


模式 3:后备链

❌ 错误做法:

ACCOUNT="claude"  # 硬编码

✅ 正确做法:

# 尝试配置项 → 尝试常见项 → 提供帮助信息的错误
ACCOUNT="${CONFIG_ACCOUNT}"
if ! has_data "$ACCOUNT"; then
    for fallback in "claude" "default" "oauth"; do
        if has_data "$fallback"; then
            ACCOUNT="$fallback"
            break
        fi
    done
fi
[[ -z "$ACCOUNT" ]] && error "未找到账户。已尝试:..."

规则: 为常见变体提供自动后备方案。


模式 4:有用的错误信息

❌ 错误做法:

[[ -z "$TOKEN" ]] && error "无令牌"

✅ 正确做法:

[[ -z "$TOKEN" ]] && error "未找到令牌

已检查:
- 配置文件:$CONFIG_FILE
- 字段名:$FIELD_NAME
- 预期格式:{ \"tokens\": { \"refresh\": \"...\" } }

验证命令:
  cat $CONFIG_FILE | jq '.tokens'
"

规则: 错误信息应帮助用户诊断和修复问题。


调试方法论(Patrick 的方法)

步骤 1:获取精确数据

不要问: “它坏了吗?”
要问: “你看到的确切值是什么?存在多少条目?哪个条目包含数据?”

示例:

# 模糊
"检查钥匙串"

# 具体
"运行:security find-generic-password -l 'Service' | grep 'acct'"
"告诉我:1. 有多少条目 2. 哪个包含令牌 3. 最后修改时间"

步骤 2:用具体示例证明

不要说: “现在应该能用了”
展示: “这是之前的令牌(POp5z...),这是之后的(01v0R...),它们不同”

模板:

之前:
- 字段1:<精确值>
- 字段2:<精确值>

之后:
- 字段1:<新值> ✅ 已改变
- 字段2:<新值> ✅ 已改变

证明:值已发生变化

步骤 3:立即考虑跨设备

不要想: “在我的机器上能运行”
要想: “如果他们的设置在 [X] 方面不同怎么办?”

检查清单:
- [ ] 不同的账户名?
- [ ] 不同的文件路径?
- [ ] 不同的工具/版本?
- [ ] 不同的权限?
- [ ] 不同的数据格式?


发布前检查清单

发现阶段

  • [ ] 列出所有外部依赖项(文件、命令、服务)
  • [ ] 记录每个依赖项提供的内容
  • [ ] 识别哪些部分可能在设备间变化

实现阶段

  • [ ] 使变量可配置(提供合理的默认值)
  • [ ] 为每个输入添加验证
  • [ ] 为常见变体构建后备链
  • [ ] 添加 --dry-run--test 模式

测试阶段

  • [ ] 使用正确配置测试 → 应正常工作
  • [ ] 使用错误配置测试 → 应回退或优雅失败
  • [ ] 使用缺失数据测试 → 应提供有用的错误信息
  • [ ] 使用多条目测试 → 应能处理歧义

文档阶段

  • [ ] 记录默认假设
  • [ ] 记录如何验证本地设置
  • [ ] 记录常见变体及处理方法
  • [ ] 包含数据流图
  • [ ] 添加故障排除部分

真实示例:OAuth 刷新器

原始版本(有缺陷)

# 假设单一条目,无验证,无后备方案
KEYCHAIN_DATA=$(security find-generic-password -s "Service" -w)
REFRESH_TOKEN=$(echo "$KEYCHAIN_DATA" | jq -r '.refreshToken')
# 使用令牌(期望它是有效的)

问题:
- 返回按字母顺序的第一个匹配项(可能是错误的条目)
- 无验证(可能为空或格式错误)
- 无后备方案(账户名不同时失败)


修复版本(便携式)

# 明确账户,带验证和后备方案
validate_data() {
    echo "$1" | jq -e '.claudeAiOauth.refreshToken' > /dev/null 2>&1
}

# 尝试配置的账户
DATA=$(security find-generic-password -s "$SERVICE" -a "$ACCOUNT" -w 2>&1)
if validate_data "$DATA"; then
    log "✓ 使用账户:$ACCOUNT"
else
    log "⚠ 尝试后备账户..."
    for fallback in "claude" "Claude Code" "default"; do
        DATA=$(security find-generic-password -s "$SERVICE" -a "$fallback" -w 2>&1)
        if validate_data "$DATA"; then
            ACCOUNT="$fallback"
            log "✓ 在 $fallback 中找到数据"
            break
        fi
    done
fi

[[ -z "$DATA" ]] || ! validate_data "$DATA" && error "未找到有效数据
已尝试账户:$ACCOUNT, claude, Claude Code, default
验证命令:security find-generic-password -l '$SERVICE'"

REFRESH_TOKEN=$(echo "$DATA" | jq -r '.claudeAiOauth.refreshToken')

改进:
- ✅ 明确的账户参数
- ✅ 验证数据结构
- ✅ 自动回退到常见名称
- ✅ 包含验证命令的有用错误信息


常见反面模式

反面模式 1:“在我的机器上能运行”

FILE="/Users/patrick/.config/app.json"  # 硬编码路径

修复: 使用 $HOME,检测操作系统,或使其可配置


反面模式 2:“期望它存在”

TOKEN=$(cat config.json | jq -r '.token')
# 如果 .token 不存在怎么办?脚本会继续使用空值

修复: 使用前验证

TOKEN=$(cat config.json | jq -r '.token // empty')
[[ -z "$TOKEN" ]] && error "配置中无令牌"

反面模式 3:“第一个匹配项就是对的”

# 如果存在多个条目,哪个是正确的?
ENTRY=$(find_entry "service")

修复: 明确指定或枚举所有

ENTRY=$(find_entry "service" "account")  # 指定具体项
# 或
ALL=$(find_all_entries "service")
for entry in $ALL; do
    validate_and_use "$entry"
done

反面模式 4:“静默失败”

process_data || true  # 忽略错误

修复: 带上下文地大声失败

process_data || error "处理数据失败
数据:$DATA
预期:{ ... }
检查命令:command_to_verify"

与现有工作流集成

与 sprint-plan.md 集成

添加到测试部分:

## 跨设备测试
- [ ] 使用不同账户名测试
- [ ] 使用错误配置值测试
- [ ] 使用缺失数据测试
- [ ] 记录后备行为

与 PRIVACY-CHECKLIST.md 集成

发布前添加:

## 可移植性检查
- [ ] 无硬编码路径(使用 $HOME,检测操作系统)
- [ ] 无硬编码名称(使用配置或后备方案)
- [ ] 对所有输入进行验证
- [ ] 为常见问题提供有用的错误信息

与 skill-creator 集成

构建新技能时:
1. 列出设备间可能变化的因素
2. 使其可配置或可自动发现
3. 使用错误配置测试
4. 记录故障排除方法


快速参考卡

编码前:
1. 设备间哪些因素会变化?
2. 如何证明它有效?
3. 当它出错时会发生什么?

强制性模式:
- 显式优于隐式
- 使用前验证
- 后备链
- 有用的错误信息

测试:
- 正确配置 → 正常工作
- 错误配置 → 回退或有用的错误信息
- 缺失数据 → 清晰的诊断信息

文档:
- 数据流图
- 常见变体
- 故障排除指南


成功标准

当工具满足以下条件时,即为便携式

  1. ✅ 无需修改即可在不同设备上工作
  2. ✅ 自动发现设置中的常见变体
  3. ✅ 优雅失败并提供可操作的错误信息
  4. ✅ 通过阅读错误输出即可调试
  5. ✅ 文档涵盖“如果我的设置不同怎么办”

测试: 将其交给设置不同的人。如果他们需要问你问题,说明工具还不够便携。


起源故事

此方法论源于调试 OAuth 刷新器(2026-01-23):
- 脚本读取了错误的钥匙串条目(未指定账户)
- 假设只存在单一条目(实际存在多个)
- 无验证(使用了空数据)
- 无后备方案(账户名不同时失败)

Patrick 的方法:
1. 要求提供精确数据(有多少条目,哪个包含令牌)
2. 要求提供证明(展示之前/之后的令牌)
3. 考虑跨设备(如果命名不同怎么办?)

结果:工具从单设备/有缺陷变为通用/生产就绪。

关键洞察: 错误不在逻辑中,而在假设中。


何时使用此技能

适用于:
- 构建读取系统配置的工具
- 处理钥匙串、凭据、环境变量
- 创建在多个机器上运行的脚本
- 向 ClawdHub 发布技能(其他人将使用它们)

应用步骤:
1. 实现前:回答三个关键问题
2. 实现中:使用强制性模式
3. 测试前:运行发布前检查清单
4. 测试后:记录变体和故障排除方法

记住: 你的设备只是一个特例。为通用情况构建。

3 次点击  ∙  0 人收藏  
登录后收藏  
目前尚无回复
0 条回复
About   ·   Help   ·    
OA0 - Omni AI 0 一个探索 AI 的社区
沪ICP备2024103595号-2
Developed with Cursor