Skip to content

설치와 제거 ​

Run은 무인으로 돌기 때문에, 빠진 게 있다면 Ticket 도중이 아니라 시작하기 전에 잡아내야 합니다. init은 Target(명령을 실행한 저장소)을 준비하고, run은 준비되지 않은 Target을 거절하고, remove는 init이 쓴 것과 Run이 남긴 것을 모두 걷어 냅니다. 그러니 내 저장소에 파이프라인을 시험해 봐도 안전합니다.

단계명령하는 일
설치npm install -g ticket-runner머신에 ticket-runner 명령을 설치
Target 준비ticket-runner init파이프라인 파일을 쓰고, GitHub를 설정하고, 나머지를 알려 줌
작업 시작ticket-runner run준비되지 않은 Target은 거절. 실행하기 참고
걷어 내기ticket-runner removeinit이 쓴 것과 Run이 남긴 것을 제거
삭제npm uninstall -g ticket-runner머신에서 명령을 삭제

요구 사항 ​

요구 사항이유확인하는 곳
Node 22 이상패키지의 engines 필드설치할 때 npm
gitTicket마다 worktree와 branch를 따로 만듦–
Target에 인증된 ghGitHub 호출은 모두 gh api로 감init이 알려 주고, gh가 없는 Host에서는 run이 거절
mattpocock-skills 플러그인 1.2.3 이상 버전이 설치된 claudeStage 하나하나가 claude -p 세션이고, implement Stage가 이 플러그인의 스킬을 실행함 (ADR-0002)둘 다 init이 알려 줌. 플러그인은 이름만 확인
Claude 요금제로 로그인한 claudeRun을 --api-key로 시작하지 않는 한, Stage는 그 로그인으로 돌고 셸이 export한 ANTHROPIC_API_KEY를 보지 못함–
Ticket이 계획되어 있는 GitHub 저장소Ticket은 보드에서 옴. Planning 참고–
이슈 트래커로 GitHub Issues를 골라 저장소에서 한 번 실행해 둔 /setup-matt-pocock-skills이 설정이 있어야 계획용 스킬이 Spec과 Ticket을 GitHub 이슈로 만듦. 실행하면 묻고 나서 docs/agents/issue-tracker.md와 CLAUDE.md의 ## Agent skills 블록을 쓰므로, 이 둘이 있으면 돌린 것–
.github/workflows의 CI 워크플로check가 하나도 없는 pull request는 merge되지 않음. gates.ci를 끄면 예외init이 알려 줌
파이프라인이 직접 돌릴 Checkpackage.json의 test, typecheck 스크립트, 또는 checks에 적은 명령init이 알려 주고, 없으면 run이 거절
main checkout에 설치된 Target 자체의 의존성Ticket의 worktree는 거기 있는 의존성을 쓰고, 따로 설치해 주는 것은 없음. 없으면 merge-base에서도 모든 Check가 실패하고, Run은 실패하는 base branch로 끝남–

merge는 base branch를 main checkout으로 pull하기만 합니다. 그러니 의존성을 추가하는 Ticket이 merge된 뒤에는 다음 Run 전에 거기서 다시 설치하세요.

플러그인은 Anthropic 공식 마켓플레이스에서 받습니다. 워크스테이션에서도 Operator가 클라우드 Host에 설치할 때와 같은 방법으로 설치합니다. 설치된 버전은 claude plugin list로 확인합니다.

bash
claude plugin marketplace add anthropics/claude-plugins-official
claude plugin install mattpocock-skills@claude-plugins-official

설치 ​

bash
npm install -g ticket-runner

업그레이드도 같은 명령입니다. 그다음 쓰던 것보다 새로운 버전마다 Release의 After upgrading을 읽으세요. init 다시 실행하기처럼 Target에서 해야 할 일이 적혀 있습니다.

GitHub의 버전 tag에서 바로 설치해도 됩니다. 이 범위는 main이 아니라 가장 높은 tag를 가리키므로, 받는 사본은 언제나 tag가 붙은, 이름 있는 버전입니다(ADR-0007).

bash
npm install -g "github:jjongs2/ticket-runner#semver:*"

init과 run은 GitHub Release로 공개된 가장 새로운 버전을 찾아봅니다. 그게 지금 사본이 보고하는 번호보다 높으면 한 줄을 출력할 뿐, 아무것도 거절하지 않습니다.

text
A newer version is out: 0.5.0, and this is 0.4.0 — upgrade with `npm install -g ticket-runner`.

지금 사본이 최신이거나 더 앞서 있을 때, 또는 GitHub에 물어볼 수조차 없을 때(네트워크나 gh가 없을 때)는 아무것도 출력하지 않습니다.

설치 없이 써 보기 ​

npx는 npm 캐시에서 패키지를 실행하므로 전역에 아무것도 설치하지 않습니다. Target에서 시작하고, 이 위키나 파이프라인의 메시지가 ticket-runner라고 하는 자리에 npx ticket-runner를 입력하세요.

bash
cd ~/code/acme
npx ticket-runner init
git add .gitignore CLAUDE.md ticket-runner.json docs/agents .claude/skills/ticket-runner
git commit -m "chore: set up ticket-runner" && git push
npx ticket-runner run
npx ticket-runner remove   # 다 써 봤으면
하려는 일입력
예전에 캐시된 것 말고 가장 새 버전 쓰기npx ticket-runner@latest …
명령마다 같은 버전 쓰기npx ticket-runner@<version> …
npx가 남긴 것 지우기~/.npm/_npx 삭제

init으로 Target 준비하기 ​

bash
cd ~/code/acme
ticket-runner init

commit은 하지 않습니다. 첫 Run 전에 쓴 내용을 commit해서 base branch에 push하세요. Ticket의 worktree는 remote에서 branch를 따 오니, Stage는 base branch에 들어간 뒤에야 conventions 문서를 읽고, 클라우드 Host는 push된 것만 봅니다. Ticket을 claim하지 않으므로 Run lock도 잡지 않습니다.

쓰는 것 ​

항목위치다음 init에서는
.gitignore 줄 두 개.gitignore: .worktrees/, .ticket-runner/어떤 표기로든 이미 무시하고 있으면 추가하지 않음
빈 설정 파일{}만 담긴 ticket-runner.json한번 생기면 건드리지 않음
버전이 찍힌 conventions 문서docs/agents/pipeline-conventions.md내용이 다르면 다시 씀
그 문서를 가리키는 섹션CLAUDE.md, 없으면 새로 만듦CLAUDE.md가 이미 문서를 가리키면 추가하지 않음
Operator의 스킬.claude/skills/ticket-runner/SKILL.md내용이 다르면 다시 씀

conventions 문서와 스킬은 파이프라인의 글이라, 거기서 고친 내용은 다음 init에서 사라집니다. 예외가 하나 있습니다. 문서 첫 줄에는 숨은 <!-- ticket-runner:version <number> --> 표시가 있는데, 이 표시가 지금 실행 중인 것보다 새 버전을 가리키면 init은 문서와 스킬을 그대로 두고 업그레이드하라고만 알립니다. 다시 쓰면 Target을 과거로 되돌리는 셈이기 때문입니다.

GitHub에서 하는 일 ​

설정init이 하는 일
triage 라벨 여섯 개(needs-triage, needs-info, ready-for-agent, ready-for-human, wontfix, in-progress)없는 것만 labels가 정한 이름으로 만들고, 나머지는 그대로 둠
squash merge켬. 다른 merge 방식은 건드리지 않음
merge될 때 pull request branch 삭제켬. 클라우드 Host는 branch를 직접 지울 수 없기 때문(ADR-0008)

gh가 인증되어 있지 않으면 GitHub에서는 아무것도 하지 않고, 보고서에 그렇게 적습니다. 이 설정을 바꾸려면 gh 사용자에게 저장소 설정을 바꿀 권한이 있어야 합니다. merge 시 branch를 지우는지는 GitHub가 그런 사용자에게만 알려 주므로, 다른 사람이 시작한 Run은 그 설정이 꺼진 것처럼 거절됩니다.

알려 주기만 하는 것 ​

text
ticket-runner 0.5.2 init · /home/me/code/acme

Wrote:
  nothing to write

GitHub:
  labels: every triage label is already there
  merges: squash merging is on, and no other merge method was touched
  branches: a pull request's branch is already deleted when it merges

Checked:
  ✓ `gh` is authenticated
  ✓ `claude` runs
  ✓ the `mattpocock-skills` plugin is installed
  ✗ no CI workflow in `.github/workflows` — a pull request with no checks is never merged
  ✓ a Check is configured or inferable: npm test, npm run typecheck

Not ready: 1 item is yours to put right.

.github/workflows에 .yml이나 .yaml 파일이 하나라도 있으면 워크플로가 있다고 봅니다.

종료 코드뜻
0알려 준 항목이 모두 통과
1사람이 고칠 항목이 하나 이상 남음
2거절: Stage의 셸이거나 ticket-runner.json이 잘못됨

그래서 ticket-runner init && ticket-runner run은 어차피 안 될 Run을 시작하기 전에 멈춥니다.

Target 준비 상태: run이 거절하는 경우 ​

run은 아무것도 고치지 않습니다. init이 뒀어야 할 항목이 있는지 이 순서로 확인하고, 처음 빠진 항목에서 종료 코드 2로 거절합니다. 어느 Host에서나 똑같이 확인하므로, 워크스테이션의 Run이 받아들인 Target은 Operator가 Claude 앱에서 돌려도 받아들여집니다.

순서거절하는 경우
1.gitignore가 .worktrees/나 .ticket-runner/를 무시하지 않음
2docs/agents/pipeline-conventions.md가 없거나 버전 표시가 없음
3CLAUDE.md가 그 문서의 경로를 언급하지 않음
4Operator의 스킬이 없음
5gh가 설치되어 있지 않음. 이때는 init보다 설치를 먼저 안내
6labels가 정한 이름의 triage 라벨이 하나라도 없음
7저장소가 merge된 pull request의 branch를 남겨 둠
8remote의 base branch(예: origin/main)에 2, 3, 4번 항목 중 하나가 없음. worktree는 모두 여기서 만들어지므로, init을 다시 돌리라는 대신 init이 쓴 것을 commit하고 push하라고 안내
text
$ ticket-runner run
This Target is not set up: `.gitignore` does not ignore `.worktrees/`. Run `ticket-runner init` here and start again; a Run puts nothing in place itself.

준비 상태 확인은 있는지와 버전 표시만 보고, 내용은 보지 않습니다. 다른 버전이 쓴 conventions 문서는 경고로 그치고, Run은 그대로 진행합니다.

text
warning: This Target's `docs/agents/pipeline-conventions.md` was left by 0.4.0, and this Run is 0.5.2 — run `ticket-runner init` here to bring it up to date.

준비 상태 확인보다 먼저 오는 거절이 하나 있습니다. 클라우드 Host에서, 또는 ANTHROPIC_API_KEY를 export하지 않고 --api-key를 준 경우입니다.

준비 상태 확인 다음에 거절이 두 가지 더 있습니다.

  • checkout에 남은 state file. 초기 파이프라인은 Ticket의 재개 상태를 .ticket-runner/state/에 뒀는데, 지금은 Target의 remote에 두고, 옮겨 주는 것은 없습니다. 이 디렉터리에 state file이 남아 있으면 Run은 해당 Ticket을 나열하며 거절합니다. 그 파일을 쓴 버전으로 Ticket을 마무리하거나 사람에게 넘긴 다음, 디렉터리를 지우세요.
  • Check 없음. Checks 게이트가 켜져 있는데 설정하거나 추론할 수 있는 Check 명령이 없으면, 검사하지 않은 코드를 merge하느니 Run을 거절합니다.

remove로 걷어 내기 ​

bash
cd ~/code/acme
ticket-runner remove        # 지울 목록을 보여 주고 물어봄
ticket-runner remove --yes  # 묻지 않고 그대로

remove는 파이프라인이 뒀다고 증명할 수 있는 것만 걷어 냅니다. commit은 하지 않으니 git status로 바뀐 내용을 살펴보고 직접 commit하세요. 작업하는 동안 Run lock을 잡아서, 해체 중인 Target에서 Run이 시작되지 않게 합니다.

거절할 때는 언제나 다음에 할 일을 알려 줍니다. lock이 잡혀 있으면 누가 잡았든 거절됩니다. 이 Host에서 프로세스가 사라진 Run이 잡고 있어도 마찬가지입니다. remove는 lock을 넘겨받지 않으니, ticket-runner run을 시작해 그 Run이 맡고 있던 일을 마무리하거나 직접 lock을 푸세요(Hand-off, 멈추고 이어 하기). 클라우드 Host는 remote의 branch를 지울 수 없어서 거절합니다. remove는 워크스테이션에서 실행하세요.

사라지는 것과 남는 것 ​

제거하는 것:

  • docs/agents/pipeline-conventions.md, Operator의 스킬, 그 결과 비게 된 디렉터리
  • init이 쓴 CLAUDE.md 섹션. 그 섹션뿐인 파일이면 파일째 지웁니다.
  • init이 쓴 주석 아래 그대로 있는 .gitignore 줄. 그 줄뿐인 파일이면 파일째 지웁니다.
  • .ticket-runner/: Run 로그와 transcript
  • .worktrees/ticket-<n> worktree와 그 branch, 다른 로컬 agent/ branch, 비게 된 .worktrees/
  • in-progress 라벨. 달고 있던 모든 이슈에서 뗍니다.
  • ticket-runner/state branch. 이제 재개할 수 없게 된 Ticket을 보고서가 모두 알려 줍니다.
  • ticket-runner.json. 맨 마지막에, 앞의 제거가 모두 성공했을 때만 지웁니다.
  • ticket-runner/lock branch. 맨 마지막에 지우고, 실패한 제거가 있으면 지우지 않고 lock만 풉니다.

남겨 두는 것:

  • in-progress를 뺀 triage 라벨 다섯 개. Planning에서도 쓰기 때문입니다.
  • 문구를 고친 CLAUDE.md 섹션. 이제 사람의 것일 수 있어서입니다.
  • 사람이 단 주석 아래 있는 .gitignore 줄
  • 다른 것이 들어 있는 .worktrees/, 그리고 그 .gitignore 줄
  • squash merge와 merge 시 branch 삭제 설정. init 전부터 켜져 있었을 수 있습니다.
  • GitHub의 agent/ branch와 거기 열린 pull request
  • 상설 Notes 이슈, 그리고 Run이 쓴 모든 코멘트. 사람에게 쓴 글이라서입니다.

실패한 제거는 보고하고 나머지는 계속 진행합니다. remove를 다시 실행하면 남은 것을 대상으로 처음부터 다시 하는 셈입니다.

종료 코드뜻
0모두 사라졌거나, 지울 것이 없었음
1제거가 하나 이상 실패
2아무것도 바꾸기 전에 거절

삭제 ​

bash
npm uninstall -g ticket-runner

Target마다 먼저 ticket-runner remove를 실행하세요. 명령을 지운 뒤에는 할 수 없습니다.

참고 자료 ​