skeeper

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Skeeper Reference Guide

Skeeper参考指南

Comprehensive reference for the
skeeper
CLI: a Go binary that mirrors spec artifacts into a sidecar Git repository with a tracked lockfile, so a main repository's PR diffs stay focused on code and every commit can prove which spec state shipped with it.
本指南是
skeeper
CLI的综合参考文档:这是一个Go语言编写的二进制工具,可将规范工件镜像到侧仓Git仓库中,并通过跟踪锁文件确保主仓库的PR diff仅聚焦于代码,且每个提交都能证明对应的规范版本随代码一同发布。

What Is Skeeper

什么是Skeeper

  • Lockfile-backed reliability.
    skeeper.lock
    is committed to the main repo and pins each main commit to exact sidecar commits per namespace, with content digests, file counts, and byte counts.
  • Strict managed hooks.
    pre-commit
    and
    pre-merge-commit
    mirror staged content, push the sidecar, write
    skeeper.lock
    , and stage it before Git creates the main commit.
    pre-push
    re-verifies the lock against the sidecar remote.
  • Namespaces in shared sidecars. Many projects can share one sidecar Git remote without colliding because each project owns a namespace prefix and uses branch-aware refs of the form
    <namespace>/__branches__/<source-branch>
    .
  • Safe drift handling.
    diff
    ,
    hydrate
    ,
    reconcile
    ,
    rescue
    , and
    update
    protect local managed documents: Skeeper reports drift first, fails closed before overwrites, and preserves pruned files under
    .git/skeeper/rescue/
    .
  • Single-binary, local-first. Skeeper shells out to
    git
    (and
    gh
    only when
    skeeper init
    creates a brand-new sidecar repo). Every operation is debuggable with the same Git commands you already know.
  • 基于锁文件的可靠性
    skeeper.lock
    会提交到主仓库,它将主仓库的每个提交与侧仓中每个命名空间的精确提交进行绑定,包含内容摘要、文件数量和字节数。
  • 严格的托管钩子
    pre-commit
    pre-merge-commit
    钩子会镜像暂存的内容、推送侧仓、写入
    skeeper.lock
    并将其暂存,之后Git才会创建主仓库的提交。
    pre-push
    钩子会在推送前重新验证锁文件与侧仓远程仓库的一致性。
  • 共享侧仓中的命名空间:多个项目可以共享同一个侧仓Git远程仓库而不会产生冲突,因为每个项目都拥有一个命名空间前缀,并使用
    <namespace>/__branches__/<source-branch>
    形式的分支感知引用。
  • 安全的漂移处理
    diff
    hydrate
    reconcile
    rescue
    update
    命令可保护本地托管文档:Skeeper会先报告漂移情况,在覆盖前会失败终止,并将已删除的文件保留在
    .git/skeeper/rescue/
    目录下。
  • 单二进制、本地优先:Skeeper通过调用
    git
    命令运行(仅在
    skeeper init
    创建全新侧仓仓库时会调用
    gh
    )。所有操作都可以用你熟悉的Git命令进行调试。

Mental Model: Four Invariants

核心模型:四个不变原则

  1. skeeper.lock
    is the source of truth.
    It records sidecar URL, source branch, namespace branch, sidecar commit SHA, content digest, file count, and byte count. Hydrate, verify, and fsck all read from it. Never edit SHAs by hand.
  2. Sync happens before the main commit, not after. Failure fails the commit. There is no async retry queue.
  3. Failure fails closed unless you opt out.
    SKEEPER_SKIP=1
    allows a single bypass that is recorded to
    .git/skeeper/bypass.json
    and surfaced in
    status
    ,
    fsck
    , and
    pre-push
    until cleared by
    skeeper sync
    .
    git commit --no-verify
    is unsupported because Git skips all hook code.
  4. pre-push
    re-verifies before the remote sees the commit.
    A bypassed or stale lock blocks the push.
mermaid
flowchart LR
    A[git commit] --> B[existing user hook content]
    B --> C[skeeper pre-commit block]
    C --> D[reconcile staged specs and ownership]
    D --> E[fetch and rebase sidecar branch]
    E --> F[mirror namespace files into .skeeper/]
    F --> G[commit and push sidecar]
    G --> H[write and stage skeeper.lock]
    H --> I[main commit proceeds]
    I --> J[git push]
    J --> K[skeeper pre-push verify]
  1. skeeper.lock
    是事实来源
    :它记录了侧仓URL、源分支、命名空间分支、侧仓提交SHA、内容摘要、文件数量和字节数。Hydrate、verify和fsck命令都会读取该文件。切勿手动编辑SHA值。
  2. 同步操作在主提交之前执行,而非之后:同步失败会导致提交失败,不存在异步重试队列。
  3. 失败默认终止,除非主动选择退出:设置
    SKEEPER_SKIP=1
    允许单次绕过,该操作会记录到
    .git/skeeper/bypass.json
    中,并在
    status
    fsck
    pre-push
    命令中显示,直到执行
    skeeper sync
    清除记录。不支持
    git commit --no-verify
    ,因为Git会跳过所有钩子代码。
  4. pre-push
    会在远程仓库收到提交前重新验证
    :绕过或过期的锁文件会阻止推送操作。
mermaid
flowchart LR
    A[git commit] --> B[existing user hook content]
    B --> C[skeeper pre-commit block]
    C --> D[reconcile staged specs and ownership]
    D --> E[fetch and rebase sidecar branch]
    E --> F[mirror namespace files into .skeeper/]
    F --> G[commit and push sidecar]
    G --> H[write and stage skeeper.lock]
    H --> I[main commit proceeds]
    I --> J[git push]
    J --> K[skeeper pre-push verify]

Quick Start

快速开始

bash
undefined
bash
undefined

Inside any Git repository

在任意Git仓库内执行

skeeper init # interactive: pick sidecar mode, namespace, patterns skeeper hooks install # one-time per clone $EDITOR src/auth/SPEC.md git add src/auth/service.go src/auth/SPEC.md git commit -m "auth: design OAuth provider flow"
skeeper init # 交互式操作:选择侧仓模式、命名空间、匹配规则 skeeper hooks install # 每个克隆仓库只需执行一次 $EDITOR src/auth/SPEC.md git add src/auth/service.go src/auth/SPEC.md git commit -m "auth: design OAuth provider flow"

the hook syncs the sidecar and stages skeeper.lock; commit it normally

钩子会同步侧仓并暂存skeeper.lock;正常提交即可

git push

If the working tree already contains specs that should be sidecar-managed, run `skeeper adopt <glob>` after `init` to migrate them in one transaction.
git push

如果工作区中已有需要由侧仓管理的规范文件,可在`init`之后执行`skeeper adopt <glob>`命令,一次性将它们迁移到侧仓管理。

Command Map

命令映射表

CommandPurposeRead-only?
skeeper init
Interactively bootstrap
.skeeper.yml
, the sidecar repo, and the managed
.gitignore
block
no
skeeper hydrate
Restore spec files from the sidecar commits recorded in
skeeper.lock
no
skeeper sync
Mirror current specs to the sidecar and stage
skeeper.lock
no
skeeper adopt <path-or-glob>...
Move main-tracked specs under sidecar coverageno
skeeper untrack <path-or-glob>...
Reverse adoption: stop tracking specs in the main repono
skeeper pattern test <glob>
Preview which working-tree files a glob would matchyes
skeeper pattern add <glob>
Add a glob to a namespace and update
.skeeper.yml
and
.gitignore
no
skeeper status
Show sidecar URL, branch, lock state, namespace digests, repair, bypassyes
skeeper log <path>
Show sidecar history for a single spec file (default: locked commit;
--latest
reads tip)
yes
skeeper fsck
Compare working-tree specs against
skeeper.lock
yes
skeeper diff
List path-level drift classes such as local-only, missing, modified, and conflictyes
skeeper reconcile
Resolve drift explicitly by adopting, pruning to rescue, merging, or choosing ours/theirsno
skeeper verify
Validate
skeeper.lock
against the sidecar remote
yes
skeeper hooks install
Install or refresh the strict hooks,
.gitattributes
, and merge driver
no
skeeper hooks check
Validate that managed hook blocks and the merge driver are wired correctlyyes
skeeper merge-driver
Regenerate
skeeper.lock
during Git merges (called by
.gitattributes
)
no
skeeper rescue list
List rescue manifests for files moved aside before prune or overwriteyes
skeeper rescue restore <id>
Restore all or selected files from a rescue manifestno
skeeper update
Agent-friendly update workflow: fast-forward, verify, hydrate, fsck, hooksno
skeeper repair status
Show the active transaction and any pending bypassyes
skeeper repair resume
Re-run the recorded plan after a transient failureno
skeeper repair abort
Clear the transaction (only safe before main-index mutation)no
skeeper version
Print build metadatayes
--json
produces deterministic machine-readable output on every command marked above.
--dry-run
is supported on every mutating command.
--force
overrides the broad-plan guardrails declared under
settings.guardrails
.
For full per-flag detail, read
references/cli-reference.md
.
命令用途是否只读
skeeper init
交互式引导创建
.skeeper.yml
、侧仓仓库和托管的
.gitignore
skeeper hydrate
根据
skeeper.lock
中记录的侧仓提交恢复规范文件
skeeper sync
将当前规范文件镜像到侧仓并暂存
skeeper.lock
skeeper adopt <path-or-glob>...
将主仓库跟踪的规范文件纳入侧仓管理
skeeper untrack <path-or-glob>...
取消侧仓管理:停止在主仓库跟踪规范文件
skeeper pattern test <glob>
预览通配符会匹配工作区中的哪些文件
skeeper pattern add <glob>
向命名空间添加通配符,并更新
.skeeper.yml
.gitignore
skeeper status
显示侧仓URL、分支、锁文件状态、命名空间摘要、修复记录、绕过记录
skeeper log <path>
显示单个规范文件的侧仓历史记录(默认:锁定的提交;
--latest
读取最新提交)
skeeper fsck
对比工作区规范文件与
skeeper.lock
的一致性
skeeper diff
列出路径级别的漂移类型,如本地独有、缺失、已修改、冲突
skeeper reconcile
通过纳入本地修改、修剪至救援目录、合并或选择本地/远程版本来明确解决漂移
skeeper verify
验证
skeeper.lock
与侧仓远程仓库的一致性
skeeper hooks install
安装或刷新严格钩子、
.gitattributes
和合并驱动
skeeper hooks check
验证托管钩子块和合并驱动是否正确配置
skeeper merge-driver
在Git合并期间重新生成
skeeper.lock
(由
.gitattributes
调用)
skeeper rescue list
列出在修剪或覆盖前被移至救援目录的文件清单
skeeper rescue restore <id>
从救援清单中恢复全部或选定文件
skeeper update
适用于代理的更新工作流:快进、验证、hydrate、fsck、钩子检查
skeeper repair status
显示当前活动事务和任何待处理的绕过记录
skeeper repair resume
在临时故障后重新运行已记录的计划
skeeper repair abort
清除事务(仅在主索引未修改时安全)
skeeper version
打印构建元数据
--json
参数可为上述所有命令生成确定的机器可读输出。
--dry-run
参数支持所有修改类命令。
--force
参数会覆盖
settings.guardrails
中声明的全局计划防护规则。
如需了解每个参数的详细信息,请阅读
references/cli-reference.md

Configuration Cheatsheet

配置速查表

.skeeper.yml
lives at the repository root and is committed. The minimum required shape:
yaml
sidecar: git@github.com:user/myproject-specs.git

namespaces:
  - name: project
    patterns:
      - "**/SPEC.md"
      - "docs/specs/**"
      - ".claude/plans/**"
      - "**/*.spec.md"
    exclude:
      - "docs/specs/private/**"
Optional operational defaults:
yaml
settings:
  guardrails:
    max_files: 100 # default 100
    max_bytes: 10485760 # default 10 MiB
  hooks:
    pre_push_timeout: 30s # default 30s
    allow_skip_env: SKEEPER_SKIP # default SKEEPER_SKIP
Four rules to know:
  1. Unknown keys are rejected. Decode is strict.
  2. exclude
    is the only public exclusion mechanism.
    Negative globs (
    !docs/private/**
    ) inside
    patterns
    are rejected.
  3. Ownership must be unique. If two namespaces match the same file, the plan fails with a request to add an
    exclude
    .
  4. __branches__
    is reserved.
    It is the segment that separates a namespace from its branch-aware refs.
For the full schema with every field and default, read
references/config-reference.md
.
.skeeper.yml
位于仓库根目录并需要提交到仓库。最小必填配置如下:
yaml
sidecar: git@github.com:user/myproject-specs.git

namespaces:
  - name: project
    patterns:
      - "**/SPEC.md"
      - "docs/specs/**"
      - ".claude/plans/**"
      - "**/*.spec.md"
    exclude:
      - "docs/specs/private/**"
可选的操作默认配置:
yaml
settings:
  guardrails:
    max_files: 100 # 默认值100
    max_bytes: 10485760 # 默认值10 MiB
  hooks:
    pre_push_timeout: 30s # 默认值30s
    allow_skip_env: SKEEPER_SKIP # 默认值SKEEPER_SKIP
需要了解的四条规则:
  1. 未知键会被拒绝:配置解码是严格的。
  2. exclude
    是唯一公开的排除机制
    patterns
    中的负通配符(如
    !docs/private/**
    )会被拒绝。
  3. 文件归属必须唯一:如果两个命名空间匹配同一个文件,计划会失败,并要求添加
    exclude
    规则。
  4. __branches__
    是保留字段
    :它是分隔命名空间与其分支感知引用的段。
如需查看包含所有字段和默认值的完整架构,请阅读
references/config-reference.md

Common Workflows

常见工作流

Bootstrap a new repository

引导新仓库

bash
skeeper init \
  --sidecar-name myproject-specs \
  --visibility private \
  --namespace project \
  --patterns "**/SPEC.md" \
  --patterns "docs/specs/**"
skeeper hooks install
git add .skeeper.yml .gitignore
git commit -m "chore: bootstrap skeeper"
bash
skeeper init \
  --sidecar-name myproject-specs \
  --visibility private \
  --namespace project \
  --patterns "**/SPEC.md" \
  --patterns "docs/specs/**"
skeeper hooks install
git add .skeeper.yml .gitignore
git commit -m "chore: bootstrap skeeper"

Join a repo with an existing sidecar

加入已有侧仓的仓库

bash
skeeper init --sidecar git@github.com:user/shared-specs.git \
  --namespace project \
  --patterns "**/SPEC.md"
skeeper hydrate
skeeper init
installs or refreshes the managed hooks and merge driver. Run
skeeper hooks install
explicitly when upgrading an older clone or repairing hook drift.
bash
skeeper init --sidecar git@github.com:user/shared-specs.git \
  --namespace project \
  --patterns "**/SPEC.md"
skeeper hydrate
skeeper init
会安装或刷新托管钩子和合并驱动。升级旧克隆仓库或修复钩子漂移时,请显式执行
skeeper hooks install

Adopt files already in the main repo

纳入主仓库中已有的文件

bash
skeeper pattern test "docs/adrs/**"          # confirm matches
skeeper adopt --dry-run "docs/adrs/**"        # preview move
skeeper adopt "docs/adrs/**"                  # execute
git commit -m "chore: adopt ADRs into sidecar"
bash
skeeper pattern test "docs/adrs/**"          # 确认匹配的文件
skeeper adopt --dry-run "docs/adrs/**"        # 预览迁移操作
skeeper adopt "docs/adrs/**"                  # 执行迁移
git commit -m "chore: adopt ADRs into sidecar"

Recover after a failed push

推送失败后恢复

bash
skeeper repair status
bash
skeeper repair status

transaction: <id> (<phase>)

事务:<id> (<阶段>)

fix the underlying network/auth/contention issue, then:

修复底层网络/权限/冲突问题后执行:

skeeper repair resume
skeeper repair resume

or, only before main-index mutation:

或者,仅在主索引未修改时执行:

skeeper repair abort
undefined
skeeper repair abort
undefined

Inspect and resolve local drift

检查并解决本地漂移

bash
skeeper diff --modified
skeeper hydrate --dry-run
skeeper reconcile --adopt-local
bash
skeeper diff --modified
skeeper hydrate --dry-run
skeeper reconcile --adopt-local

or preserve local-only files before restoring locked content:

或者在恢复锁定内容前保留本地独有文件:

skeeper reconcile --prune-local skeeper rescue list

Use `reconcile --adopt-local` when local edits are the intended spec state. Use `reconcile --prune-local` when local-only files should be preserved in `.git/skeeper/rescue/<id>/` before restoring the locked sidecar content. Use `--merge`, `--ours`, or `--theirs` only when that conflict policy is explicit.
skeeper reconcile --prune-local skeeper rescue list

当本地编辑是预期的规范状态时,使用`reconcile --adopt-local`。当本地独有文件需要在恢复锁定的侧仓内容前保留到`.git/skeeper/rescue/<id>/`目录时,使用`reconcile --prune-local`。仅当冲突策略明确时,才使用`--merge`、`--ours`或`--theirs`。

Update a fresh clone or agent worktree

更新新克隆或代理工作区

bash
skeeper update
skeeper update --reconcile keep-local
update
is the high-level workflow for agents and fresh clones: it fetches and fast-forwards when safe, verifies
skeeper.lock
, hydrates managed files, runs
fsck
, and validates hooks.
bash
skeeper update
skeeper update --reconcile keep-local
update
是适用于代理和新克隆仓库的高级工作流:它会在安全时拉取并快进、验证
skeeper.lock
、恢复托管文件、执行
fsck
并验证钩子配置。

Resolve a
skeeper.lock
merge conflict

解决
skeeper.lock
合并冲突

bash
git merge feature/auth-redesign
bash
git merge feature/auth-redesign

.gitattributes routes lock conflicts through skeeper merge-driver automatically

.gitattributes会自动将锁文件冲突路由到skeeper合并驱动处理

if you resolved by hand:

如果手动解决了冲突:

skeeper sync git add skeeper.lock git commit
undefined
skeeper sync git add skeeper.lock git commit
undefined

CI Integration

CI集成

Same-repository GitHub Action wraps the released binary:
yaml
name: skeeper

on:
  pull_request:
  push:
    branches: [main]

jobs:
  verify:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: compozy/skeeper@v0.2.1
        with:
          args: |
            verify
            --json
          ssh-private-key: ${{ secrets.SKEEPER_SSH_PRIVATE_KEY }}
Credential precedence:
  1. ssh-private-key
    writes a temp key and sets
    GIT_SSH_COMMAND
    . The key is wiped on cleanup.
  2. token
    configures HTTPS GitHub credentials in a per-job
    GIT_CONFIG_GLOBAL
    .
  3. The runner's existing Git/SSH config is used when neither input is provided.
Secrets are always masked through
::add-mask::
before configuration.
同仓库GitHub Action封装了已发布的二进制文件:
yaml
name: skeeper

on:
  pull_request:
  push:
    branches: [main]

jobs:
  verify:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: compozy/skeeper@v0.2.1
        with:
          args: |
            verify
            --json
          ssh-private-key: ${{ secrets.SKEEPER_SSH_PRIVATE_KEY }}
凭证优先级:
  1. ssh-private-key
    会写入临时密钥并设置
    GIT_SSH_COMMAND
    。密钥会在清理时被删除。
  2. token
    会在每个作业的
    GIT_CONFIG_GLOBAL
    中配置HTTPS GitHub凭证。
  3. 当未提供上述两个输入时,会使用运行器现有的Git/SSH配置。
凭证会在配置前通过
::add-mask::
进行掩码处理。

When NOT To Use Skeeper

何时不应使用Skeeper

  • Repos that already version specs in the main tree and want them to appear in PR diffs alongside code. Skeeper exists to keep specs out of those diffs.
  • Teams that need PR review on the spec content itself before merge. Skeeper mirrors after the main commit succeeds, so spec review must happen against the sidecar repo or against the main-tree working copy before commit.
  • Repos without a stable sidecar host. Skeeper requires a Git remote that the working tree can reach during commit; an unreachable remote means every commit fails closed unless someone uses
    SKEEPER_SKIP=1
    .
  • Storing build artifacts, generated code, or large binaries. Skeeper is for spec-shaped text artifacts. Guardrails default to 100 files and 10 MiB per plan precisely to keep it that way.
  • 已在主仓库中管理规范文件且希望它们出现在PR diff中与代码一同展示的仓库。Skeeper的存在目的是让规范文件远离这些diff。
  • 需要在合并前对规范内容进行PR评审的团队。Skeeper会在主提交成功后镜像规范文件,因此规范评审必须针对侧仓仓库或提交前的主仓库工作区进行。
  • 没有稳定侧仓托管服务的仓库。Skeeper要求工作区在提交期间能够访问Git远程仓库;无法访问远程仓库意味着每次提交都会失败,除非有人使用
    SKEEPER_SKIP=1
  • 存储构建工件、生成代码或大型二进制文件的场景。Skeeper适用于规范类文本工件。防护规则默认限制为100个文件和10 MiB,正是为了确保这一点。

Anti-Patterns for Agents

代理使用的反模式

  1. Never use
    git commit --no-verify
    on a skeeper-enabled repo.
    Use
    SKEEPER_SKIP=1
    instead so the bypass is audited.
  2. Never edit SHAs in
    skeeper.lock
    by hand.
    Use
    skeeper sync
    or
    skeeper merge-driver
    to regenerate.
  3. Never reuse a sidecar remote across projects without unique namespaces. Skeeper requires unambiguous routing; ownership must be unique per file.
  4. Never run
    skeeper repair abort
    after the main index has been mutated.
    Use
    skeeper repair resume
    instead, or fix the sidecar manually if the sidecar has already received the push.
  5. Never bypass with
    SKEEPER_SKIP=1
    and forget to run
    skeeper sync
    afterward.
    The bypass keeps surfacing in
    status
    ,
    fsck
    , and
    pre-push
    until cleared.
  6. Never put negative globs in
    patterns
    .
    Use
    exclude
    instead; the loader rejects negative globs explicitly.
  7. Never delete
    skeeper.lock
    to "fix" a merge conflict.
    Resolve it via the merge driver, then run
    skeeper verify
    .
  8. Never assume
    skeeper hydrate
    chases the latest tip.
    It restores from the locked commits;
    --latest
    only exists on
    skeeper log
    .
  9. Never force hydrate/reconcile over local managed files without classifying drift first. Run
    skeeper diff
    and choose
    --adopt-local
    ,
    --prune-local
    ,
    --merge
    ,
    --ours
    , or
    --theirs
    deliberately.
  1. 切勿在启用skeeper的仓库中使用
    git commit --no-verify
    :请改用
    SKEEPER_SKIP=1
    ,这样绕过操作会被审计记录。
  2. 切勿手动编辑
    skeeper.lock
    中的SHA值
    :使用
    skeeper sync
    skeeper merge-driver
    重新生成。
  3. 切勿在无唯一命名空间的情况下跨项目复用侧仓远程仓库:Skeeper需要明确的路由规则;每个文件的归属必须唯一。
  4. 切勿在主索引已修改后执行
    skeeper repair abort
    :请改用
    skeeper repair resume
    ,如果侧仓已收到推送,请手动修复侧仓。
  5. 切勿使用
    SKEEPER_SKIP=1
    绕过之后忘记执行
    skeeper sync
    :绕过记录会一直显示在
    status
    fsck
    pre-push
    命令中,直到被清除。
  6. 切勿在
    patterns
    中使用负通配符
    :请改用
    exclude
    ;加载器会明确拒绝负通配符。
  7. 切勿删除
    skeeper.lock
    来“修复”合并冲突
    :请通过合并驱动解决冲突,然后执行
    skeeper verify
  8. 切勿假设
    skeeper hydrate
    会获取最新提交
    :它会从锁定的提交中恢复;
    --latest
    仅在
    skeeper log
    命令中存在。
  9. 切勿在未先分类漂移的情况下强制覆盖本地托管文件:请先执行
    skeeper diff
    ,然后有针对性地选择
    --adopt-local
    --prune-local
    --merge
    --ours
    --theirs

References

参考文档

  • references/cli-reference.md
    — every command, every flag, every JSON schema.
  • references/config-reference.md
    — full
    .skeeper.yml
    schema, defaults, and validation rules.
  • references/cli-reference.md
    — 所有命令、参数和JSON架构。
  • references/config-reference.md
    — 完整的
    .skeeper.yml
    架构、默认值和验证规则。