@kaydash9999/banker-plugins 0.20.5 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +52 -0
  4. package/PRIVACY.md +25 -1
  5. package/README.md +63 -18
  6. package/bin/banker.js +173 -14
  7. package/bin/lib/codex-hooks.mjs +254 -0
  8. package/bin/lib/codex-routes.mjs +112 -0
  9. package/bin/lib/command-skill.cjs +19 -0
  10. package/bin/lib/telemetry-config.mjs +4 -1
  11. package/codex/command-skills/front-qa/SKILL.md +56 -0
  12. package/codex/command-skills/setup/SKILL.md +87 -0
  13. package/codex/hooks.json +29 -0
  14. package/codex/manifest.json +13 -10
  15. package/codex/skills/graceful-pause/SKILL.md +30 -0
  16. package/codex/skills/progress/SKILL.md +42 -0
  17. package/codex/skills/progress/scripts/progress-plan.mjs +722 -0
  18. package/codex/skills/progress/scripts/progress.mjs +295 -0
  19. package/codex/transform-matrix.md +18 -13
  20. package/commands/setup.md +2 -2
  21. package/hooks/obsidize-hook.mjs +116 -4
  22. package/hooks/progress-plan.mjs +1 -1
  23. package/hooks/telemetry-count-codex.mjs +309 -0
  24. package/hooks/update-notify.mjs +105 -14
  25. package/package.json +1 -1
  26. package/skills/3d-intro-build/references/verify-intro.mjs +15 -1
  27. package/skills/anti-drm/SKILL.md +1 -1
  28. package/skills/anti-drm/scripts/instruction-toggle.mjs +57 -4
  29. package/skills/append_wiki/SKILL.md +34 -8
  30. package/skills/arch-diagram/build_pptx_template.py +47 -28
  31. package/skills/audit-web-page/SKILL.md +1 -1
  32. package/skills/audit-web-page/harness.py +0 -1
  33. package/skills/compact-wiki/SKILL.md +37 -6
  34. package/skills/deep-research/SKILL.md +6 -0
  35. package/skills/lfm/SKILL.md +148 -0
  36. package/skills/lineage/SKILL.md +14 -4
  37. package/skills/lineage/lineage.py +1582 -516
  38. package/skills/motion-graphic-make/SKILL.md +1 -1
  39. package/skills/obsidizer/SKILL.md +44 -10
  40. package/skills/obsidizer/obsidize.mjs +42 -11
  41. package/skills/omc-patch/SKILL.md +6 -0
  42. package/skills/payload-mon/SKILL.md +3 -1
  43. package/skills/play-qa/SKILL.md +1 -1
  44. package/skills/ralph-qa/SKILL.md +1 -1
  45. package/skills/remains/SKILL.md +1 -1
  46. package/skills/rfp-author/SKILL.md +5 -3
  47. package/skills/rfp-author/references/vendor-rfp-structure.md +1 -1
  48. package/skills/rfp-author/scripts/md2docx.py +63 -34
  49. package/skills/setup-bypass-permissions/SKILL.md +28 -10
  50. package/skills/setup-bypass-permissions/scripts/codex-bypass.mjs +135 -0
  51. package/skills/setup-bypass-permissions/scripts/codex-config.mjs +210 -0
  52. package/skills/setup-bypass-permissions/scripts/fallback/bypass-permissions.py +66 -15
  53. package/skills/setup-omc-hud/SKILL.md +33 -3
  54. package/skills/setup-omc-hud/assets/codex-config.mjs +210 -0
  55. package/skills/setup-omc-hud/assets/codex-status-line.mjs +90 -0
  56. package/skills/smart-compact/SKILL.md +59 -13
  57. package/skills/smart-compact/scripts/codex-gate.mjs +385 -0
  58. package/skills/theme-selection/SKILL.md +1 -1
  59. package/skills/tone-compact/SKILL.md +1 -1
  60. package/skills/tone-compact/scripts/instruction-toggle.mjs +57 -4
  61. package/skills/ultra-chain/SKILL.md +10 -6
  62. package/skills/ultra-interview/SKILL.md +13 -2
  63. package/skills/ultra-ui-qa/SKILL.md +1 -1
  64. package/skills/update-banker/SKILL.md +31 -6
  65. package/skills/vertical-pptx/SKILL.md +1 -1
  66. package/skills/vertical-pptx/build_a4p.js +20 -2
  67. package/skills/vertical-pptx/build_a4p.py +560 -359
@@ -0,0 +1,19 @@
1
+ 'use strict';
2
+ /*
3
+ * A command (commands/<name>.md) as a Codex skill. Codex 0.144+ has no custom prompts, so each command is also a skill.
4
+ * Two installs use it:
5
+ * - npm (banker setup --codex): writes <CODEX_HOME>/skills/banker-<name>/SKILL.md, invoked as $banker-<name>.
6
+ * - Codex plugin (codex plugin add banker@banker-plugins): scripts/sync-codex-plugin.js writes
7
+ * codex/command-skills/<name>/SKILL.md in the repo, invoked as $banker:<name>.
8
+ * The command's description becomes the skill's. Codex skills get no $ARGUMENTS substitution, so a note says where the
9
+ * arguments come from.
10
+ */
11
+ function commandSkillText(text, name, invoke) {
12
+ const fm = text.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?/);
13
+ const desc = fm && fm[1].match(/^description:\s*(.*)$/m);
14
+ const body = fm ? text.slice(fm[0].length) : text;
15
+ const note = '> Codex: 이 명령은 스킬로 설치됐다. 본문의 `$ARGUMENTS`, `$1` 은 사용자가 `' + invoke + '` 뒤에 쓴 글이다.\n\n';
16
+ return `---\nname: ${name}\ndescription: ${desc ? desc[1] : '""'}\n---\n\n${note}${body}`;
17
+ }
18
+
19
+ module.exports = { commandSkillText };
@@ -40,6 +40,8 @@ export const USED_SKILLS_MAX = 300;
40
40
  // import 시점 resolver 결과를 캡처한다(단명 hook 프로세스용). writeUpdateCache 는 테스트 격리를 위해
41
41
  // configDir() 를 매 호출 재계산하므로 이 상수에 의존하지 않는다.
42
42
  export const UPDATE_CHECK_PATH = path.join(configDir(), 'update-check.json');
43
+ // Codex 카운팅 훅이 턴 시작을 못 찾은 Codex 판({version, notified}). 다음 Codex 세션 시작 때 한 번 알린다.
44
+ export const CODEX_SHAPE_MISS_PATH = path.join(configDir(), 'codex-shape-miss.json');
43
45
  // 업데이트 체크/체크인 스로틀 창(24h). 이 간격 미경과면 재조회하지 않는다.
44
46
  export const UPDATE_THROTTLE_MS = 24 * 60 * 60 * 1000;
45
47
 
@@ -60,7 +62,8 @@ export const SKILL_CHANGES_URL = 'https://raw.githubusercontent.com/smallOpenSou
60
62
 
61
63
  // usage-log 와 체크인 본문에 실리는 스킬/커맨드 이름 꼴. 쓰는 훅 둘과 보내는 훅이 같은 규칙을 쓴다.
62
64
  // 이름은 64자까지다(가장 긴 실제 이름은 24자). 모델이 지어낸 긴 이름이 기록과 체크인에 실리지 않게 한다.
63
- export const SKILL_NAME_RE = /^banker:[a-z0-9_-]{1,64}$/i;
65
+ // 스킬 폴더 이름은 모두 소문자라 대문자는 받지 않는다(`banker:FRONT-QA` 가 다른 이름으로 세어지지 않게).
66
+ export const SKILL_NAME_RE = /^banker:[a-z0-9_-]{1,64}$/;
64
67
 
65
68
  // 갱신 확인 요청 하나의 전체 마감(ms). 시험이 줄일 수 있게 BANKER_NET_DEADLINE_MS 를 받되 줄이기만 한다: 30초보다
66
69
  // 길면 30초다. setTimeout 이 1ms 로 바꿔 버리는 값(0 이하, 숫자 아님)도 버리고 30초를 쓴다. 문서에 적지 않는 시험용 장치다.
@@ -0,0 +1,56 @@
1
+ ---
2
+ name: front-qa
3
+ description: "스펙 파일(기본 `docs/note.md`)을 바탕으로 프론트엔드를 구현하고, 레퍼런스 구현과 같은지 엄격하게 QA 하는 워크플로(`ralplan`, `ralph`, `/loop`)."
4
+ ---
5
+
6
+ > Codex: 이 명령은 스킬로 설치됐다. 본문의 `$ARGUMENTS`, `$1` 은 사용자가 `$banker:front-qa` 뒤에 쓴 글이다.
7
+
8
+
9
+ # /front-qa — 스펙 기반 프론트엔드 구현 + 엄격 QA
10
+
11
+ `$1`(없으면 `docs/note.md`. 그 파일이 없고 `docs/note.txt` 가 있으면 그 파일)의 요구사항을 React 프론트엔드(`$FRONTEND_DIR`, 예: `apps/web`)에 구현하고,
12
+ **레퍼런스 구현(reference implementation — 예: 이전 Streamlit/타 빌드)과 엄격 비교 + 스펙 지시 정확 준수**를 검증한다. 모든 항목 해결까지 진행.
13
+
14
+ ## 0. 전제조건: OMC (없으면 설치부터)
15
+
16
+ 이 커맨드는 `/ralplan`·`/ralph` 등 oh-my-claudecode(OMC)에 의존한다. **진행 전 먼저 확인**하고, 없거나 낡았으면 **설치·갱신부터 안내**한다:
17
+ - 확인(Claude Code): `/oh-my-claudecode:*` 사용 가능 여부 + `omc` CLI 가 `ralph verify` 를 갖췄는지. OMC 5 의 `ralph` 는 첫 반복에 `omc ralph verify` 를 실행하고 없으면 멈춘다. 플러그인보다 낡은 4.x CLI 는 이 명령이 없는데도 `--help` 를 주면 전체 도움말을 찍고 종료 코드 0 을 내므로 **출력 문구로 판정**한다(`--help` 없이 부르면 Claude 실행으로 넘어가니 반드시 붙인다). Codex 는 `omx --version` 으로 OMX 를 확인한다:
18
+ ```bash
19
+ omc ralph verify --help 2>&1 | grep -q 'Usage: omc ralph verify' && echo "omc ok" || echo "omc CLI 없음 또는 낡음"
20
+ ```
21
+ - 실패하면 `/banker:setup` → oh-my-claudecode(또는 `setup-omc` 스킬 / `npm install -g oh-my-claude-sisyphus@latest`)로 먼저 구성한 뒤 이어서 진행. 점검을 통과하기 전에는 절차 1을 시작하지 않는다.
22
+ - **런타임 매핑:** 아래 절차의 `/ralplan`·`/ralph`는 Claude Code에선 OMC 스킬, **Codex에선 oh-my-codex(OMX)의 동명 스킬**이다(Codex는 OMC 대신 OMX 전제). 각 런타임에서 사용 가능한 형태로 호출한다.
23
+
24
+ ## 절차 (CLAUDE.md: 계획 없는 즉시실행 금지)
25
+
26
+ 1. **스펙 정독**: 대상 파일을 읽어 요구사항을 항목화. 코드베이스 정찰(병렬 explore/general-purpose 에이전트로
27
+ 각 항목의 현재 React 상태 ↔ 레퍼런스 구현 갭을 file:line 증거로 매핑).
28
+ 2. **`/ralplan --deliberate`**: Planner(정찰 종합)→Architect→Critic consensus(ITERATE 폐루프). Principles/Drivers/
29
+ Options(기각 사유)/pre-mortem/확장 테스트계획(unit·integration·e2e선택·observability)/ADR. 항목을 충돌-안전 순서의
30
+ 스테이지로 분해(파일 경합 시 순차, 독립 시 병렬 가능). 계획을 `.omc/plans/`에 저장.
31
+ 3. **`/ralph --critic=critic`**: 새 feature 브랜치(현 HEAD off). 스테이지별:
32
+ - executor(opus) 위임 구현 + 테스트 작성/수정.
33
+ - 🔴 **orchestrator fresh 재검증**(executor 완료보고 신뢰 금지 — 과거 오보고 사례): typecheck + 관련/전체 vitest.
34
+ - critic(opus) APPROVE까지 ITERATE.
35
+ - 로컬 커밋 + `scripts/parity-gate.sh:TEST_FLOOR` 실측 상향(같은 커밋). dead-code 제거 시 floor 하향도 정당(문서화).
36
+ - 위험 스테이지(env·deps·build·CSS토큰·스키마)는 **전체 parity-gate** 실행.
37
+ 4. **홀리스틱 리뷰(Step7)**: critic(opus)이 **스펙 N항목 逐条 충족 + 레퍼런스 parity + 교차충돌 0 + 불변 보존**을 검증(충족표).
38
+ 5. **필수 deslop(Step7.5)**: `ai-slop-cleaner` 변경 파일 범위. dead-code/중복/과추상/장황주석만(맥락 주석 보존). 무변경이면 무변경.
39
+ 6. **regression(Step7.6)** + `/oh-my-claudecode:cancel`.
40
+
41
+ ## 루프/중단 (사용자 directive)
42
+ - **/loop**: 모든 문제 해결까지 진행. credit/llm/token 비용 비고려.
43
+ - **중단 조건**: 컨텍스트 85% 도달 OR 작업 완료 → 작업·loop 중단(체크포인트: prd.json·progress.txt·메모리).
44
+
45
+ ## 🔴 불변 제약
46
+ - 보안모델: 비밀 서버사이드 주입·VITE_ 비밀 금지·`client.ts` onResponse 인터셉터 금지(openapi-fetch body 1회 소비)·
47
+ `.env`는 gitignore 유지(dist 실토큰 0).
48
+ - FSD 단방향(app→pages→widgets→features→entities→shared)·feature↔feature import 0.
49
+ - No-mock/하드코딩 금지·env 기반. **백엔드 무수정**(프론트 전용; server/auth BFF는 프론트 코드라 가능).
50
+ - 비배포 로컬도구(배포·엔드포인트 RBAC 서버강제 = 비목표). push/머지 = **사용자 통제**(원격 origin은 사용자 설정).
51
+ - 답변·문서 한글(기술 토큰 영문).
52
+
53
+ ## 완료 보고
54
+ - 스펙 항목별 결과를 **표**(항목/상태/근거 file:line)로 간결히.
55
+ - 테스트 수 변화(기준 floor→최종)·각 스테이지 critic 판정·게이트 결과.
56
+ - 미충족/수용-범위한정/후속분리 항목 정직 명시.
@@ -0,0 +1,87 @@
1
+ ---
2
+ name: setup
3
+ description: "구성요소와 의존성을 여러 개 골라 설치하는 오케스트레이터. 런타임(Node, Python, Java), LSP, tmux, MCP, 샌드박스, OMC, Playwright 등. 권한 확인 끄기는 따로 묻고 기본으로 고르지 않으며, 골라도 실행하지 않고 직접 입력할 명령만 안내."
4
+ ---
5
+
6
+ > Codex: 이 명령은 스킬로 설치됐다. 본문의 `$ARGUMENTS`, `$1` 은 사용자가 `$banker:setup` 뒤에 쓴 글이다.
7
+
8
+
9
+ # /banker:setup — 구성요소 설치 오케스트레이터
10
+
11
+ banker 플러그인이 제공하는 설치 스킬들을 **multi-select**로 골라 실행한다.
12
+ 기존 스킬들의 OS 의존성(playwright 등)을 해결하기 위함. 답변은 한글(기술 토큰 영문).
13
+
14
+ ## 절차
15
+
16
+ 0. **네트워크 확인**: 항목을 고르기 전에 원천에 닿는지 한 번 본다(curl 은 10초, npm 은 15초 안). 결과는 알림으로만 쓰고, 이것만으로 항목을 건너뛰지 않는다.
17
+ ```bash
18
+ [ "${CODEX_SANDBOX_NETWORK_DISABLED:-}" = 1 ] && echo "Codex sandbox 가 네트워크를 막음(아래 실패는 오프라인이 아님)"
19
+ in15() { "$@" & p=$!; ( sleep 15 && kill "$p" ) > /dev/null 2>&1 & k=$!; wait "$p" 2>/dev/null; r=$?; kill "$k" 2>/dev/null; wait "$k" 2>/dev/null; [ "$r" = 143 ] && echo "15초 안에 끝나지 않아 멈춤(패킷을 버리는 망일 수 있음)"; return "$r"; }
20
+ if command -v npm >/dev/null; then in15 sh -c 'cd ~ && exec npm ping --fetch-retries=0 --fetch-timeout=10000 --no-update-notifier'; else echo "npm 없음(확인하지 못함)"; fi
21
+ curl --ssl-no-revoke -sSI -o /dev/null --connect-timeout 5 --max-time 10 https://github.com
22
+ ```
23
+ - `curl -sSI` 는 머리만 받는다. 확인 줄은 `--ssl-no-revoke` 를 준다. Windows 의 Git Bash curl 도 Schannel 이라, 폐지 목록 서버에 닿지 못하는 망에서 폐지 확인이 실패하면 종료 60 이다(Windows 박스 실측). 다른 curl 은 이 깃발을 받고 무시한다(macOS curl 8.7.1, Rocky 8.10 curl 7.61.1 실측).
24
+ - 둘 다 실패하면 "네트워크가 없거나 막힌 것으로 보임. 항목마다 자기 원천을 다시 확인하고, 닿지 않는 원천에서 받는 단계는 하지 않음" 으로 먼저 알린다.
25
+ - 항목을 건너뛸지는 각 스킬의 0단계가 그 스킬의 원천으로 정한다. 사내 미러만 열린 망(`npm ping` 에 답하지 않는 npm 미러, PyPI 미러)에서도 그 원천을 쓰는 항목은 진행된다. 닿지 않는 원천에서 받는 단계만 "오프라인이라 설치하지 않음(필요한 것: <항목>)" 으로 보고된다.
26
+ - `npm` 이 아직 없으면(새 PC) npm 쪽은 오프라인이 아니라 확인하지 못한 것이다. `setup-node` 가 npm 을 깐 뒤 각 스킬의 0단계가 다시 확인한다.
27
+ - `npm ping` 은 홈 폴더에서 부른다. 지금 폴더에 있는 프로젝트의 `.npmrc` 가 정한 레지스트리와 토큰을 따르지 않게 하려는 것이다.
28
+ - `npm ping` 은 15초 감시(`in15`) 안에서 부른다. 패킷을 버리는 망에서 npm 은 연결에 시간 제한을 두지 않아(`--fetch-timeout` 은 받는 중의 쉼만 잰다) OS 의 연결 재시도가 끝날 때까지 기다린다(Rocky 8.10 실측 130초). 15초 안에 끝나지 않으면 `15초 안에 끝나지 않아 멈춤(패킷을 버리는 망일 수 있음)` 과 종료 143 이다. `--no-update-notifier` 는 npm 이 제 판을 묻는 요청을 하나 더 내지 않게 한다.
29
+ - OS 패키지 관리자(dnf, apt, brew, winget)만 쓰는 단계는 자기 설정의 미러를 쓰므로 이 확인과 관계없이 각 스킬의 규칙대로 시도한다.
30
+ - 패킷을 버리거나 답하지 않는 망에서 dnf 는 저장소마다 약 2분(SYN 을 버리는 망 실측 121초), apt 는 원천마다 약 4분(답하지 않는 원천 실측 247초) 기다린 뒤 실패로 끝난다. 시간 제한은 관리자 설정을 따르므로 이 스킬이 바꾸지 않는다.
31
+ - `apt-get update` 는 받지 못해도 종료 0 이다. 출력의 `W: Failed to fetch` 가 있으면 그 단계를 실패로 보고한다.
32
+ - 내려받기가 없는 항목(`setup-omc-hud`)과 이미 설치된 것의 확인은 그대로 진행한다.
33
+ - Windows PowerShell 에서는 `curl.exe --ssl-no-revoke -sSI -o NUL --connect-timeout 5 --max-time 10 https://github.com` 의 `$LASTEXITCODE` 로 본다. `curl.exe` 는 Windows 시스템 프록시를 따르지 않고 `HTTPS_PROXY` 만 따른다. `--ssl-no-revoke` 는 폐지 목록 서버에 닿지 못하는 망에서 Schannel 의 폐지 확인 실패를 오프라인으로 읽지 않게 한다. 닿는지만 보고 받은 내용은 쓰지 않으므로 이 확인에만 준다. `curl.exe` 가 없으면 `$LASTEXITCODE` 에 앞 명령의 값이 남으므로 `Get-Command curl.exe -ErrorAction SilentlyContinue` 로 먼저 보고, 없으면 확인하지 못한 것으로 적는다. `npm ping` 은 `Push-Location ~; npm ping --fetch-retries=0 --fetch-timeout=10000 --no-update-notifier; Pop-Location` 처럼 홈에서 부르고 돌아온다(돌아오지 않으면 뒤 단계가 프로젝트가 아니라 홈에서 돈다). PowerShell 에는 15초 감시를 두지 않는다(Windows 의 연결 시간 제한은 약 21초로 알려져 있다. 미실측).
34
+ - Codex sandbox 가 네트워크를 막는 모드(기본 `workspace-write`, `read-only`)에서는 `CODEX_SANDBOX_NETWORK_DISABLED=1` 이 서고 확인이 모두 실패한다(curl 종료 7, npm `EPERM`). 블록의 첫 줄이 그렇다고 알린다. 그때는 '오프라인' 이 아니라 'sandbox 가 네트워크를 막음' 으로 보고하고, 승인을 받아 sandbox 밖에서 확인부터 다시 한다. Claude Code sandbox 안(`SANDBOX_RUNTIME=1`)에서는 허용 목록 밖 주소를 sandbox 프록시가 막는다. Windows PowerShell 에서는 `$env:CODEX_SANDBOX_NETWORK_DISABLED -eq '1'` 로 본다.
35
+ - 확인이 실패하면 보고에 그 명령, 종료 코드, stderr 첫 줄을 붙인다(예: `npm error code ETIMEDOUT`, `curl: (28) ...`). 원인을 '오프라인' 하나로 짐작하지 않는다.
36
+ - curl 의 종료 60(인증서 검증 실패)도 오프라인이 아니다. 망은 열려 있고, TLS 를 가로채는 사내 프록시의 인증서를 OS 가 믿지 않는 것이다. '인증서 문제로 설치하지 않음' 으로 보고한다.
37
+ - curl 은 닿는데 npm 만 인증서 오류(`UNABLE_TO_VERIFY_LEAF_SIGNATURE`, `SELF_SIGNED_CERT_IN_CHAIN`, `UNABLE_TO_GET_ISSUER_CERT_LOCALLY`)로 실패하면 망은 열려 있고 npm 이 사내 인증서를 믿지 않는 것이다(npm 은 OS 인증서 저장소를 쓰지 않는다). '인증서 문제로 설치하지 않음' 으로 보고하고 `NODE_EXTRA_CA_CERTS=<사내 CA 파일>` 을 안내한다. Node 24 는 `NODE_OPTIONS=--use-system-ca` 도 된다.
38
+ - 이 실행에서 부르는 스킬의 0단계는 /banker:setup 0단계와 앞 스킬이 이미 돌린 같은 확인 줄(같은 명령과 같은 주소)의 결과를 쓰고 다시 돌리지 않는다. 처음 보는 원천만 새로 본다. 결과는 이 실행 안에서만 쓴다(그 사이 망이 바뀌면 옛 결과일 수 있다). 막힌 망에서 항목마다 같은 확인을 다시 기다리지 않게 하려는 것이다.
39
+ 1. **선택 받기**: `$ARGUMENTS` 에 컴포넌트명이 명시돼 있으면 그것만 실행(질문 생략).
40
+ 비어 있으면 아래를 `AskUserQuestion`(**multiSelect: true**)으로 제시한다(**Codex 런타임엔 AskUserQuestion 이 없으므로 목록을 제시하고 설치할 항목을 사용자에게 물어 받는다**). 항목은 **계층/의존 순서**로 묶여 있으니, 뒤 계층을 고르면 앞 계층 전제를 먼저 채운다:
41
+ - 질문 하나에 선택지는 4개까지다. 5개 이상인 묶음은 두 질문으로 나눈다.
42
+ - 맨 아래 **권한** 항목은 이 다중 선택에 넣지 않고, 그 항목의 규칙대로 따로 묻는다.
43
+
44
+ **런타임 (기반 — 먼저)**
45
+ - **setup-node** — nvm + Node 22(winget/nvm-windows). npx 기반 MCP·CLI 전제.
46
+ - **setup-python** — Python 3.11 + pipx + uv(PEP668). `setup-lsp`·`setup-mcp`·`docs-setup` 전제.
47
+ - **setup-java** — JDK 21 + JAVA_HOME(Debian=Adoptium). `setup-lsp` 의 jdtls 요구.
48
+
49
+ **개발도구**
50
+ - **setup-lsp** — 언어별 LSP(vtsls·basedpyright·bash·jdtls·spring) + lsp-mcp 브리지. (의존: node·python·java)
51
+ - **setup-tmux** — tmux(Rocky8 3.6a 소스빌드)/psmux(Windows). OMC team·OMX `$team`/HUD 전제.
52
+ - **setup-pwsh** — Windows PowerShell 7 환경($PROFILE UTF-8·Terminal·Git). 비-Windows는 no-op.
53
+ - **setup-mcp** — 공통 MCP 서버(context7·seq-thinking·filesystem·git·fetch). (의존: node·python)
54
+ - **setup-sandbox** — OS별 샌드박스(bubblewrap+userns / AppContainer / Seatbelt) + rust + git safe.directory.
55
+
56
+ **프레임워크·플러그인**
57
+ - **setup-omc** — oh-my-claudecode(OMC) 설치/갱신(Codex는 OMX). `all-in-one`·`ultra-chain`·`ultra-init`·`/banker:front-qa` 의존성.
58
+ - **setup-harness-factory** — revfactory/harness(팀 아키텍처 팩토리) 설치+구성+안내(Codex=meta-harness).
59
+ - **setup-insane-search** — insane-search 플러그인(차단 사이트 우회, Claude/Codex 양쪽).
60
+ - **setup-omc-hud** — omc_hud 상태표시줄(래퍼 v4, 스킬에 든 파일로 오프라인 설치).
61
+ - **setup-stitch** — Stitch(디자인 생성) MCP 프록시 등록(RockyLinux8 proxy-script, API key 필요).
62
+
63
+ **의존성 라이브러리**
64
+ - **setup-playwright** — Playwright + 브라우저 + Xvfb(RHEL8/Rocky8 폴백). (`ultra-ui-qa`·`audit-web-page`·`play-qa`·`ultra-chain` 의존성)
65
+ - **docs-setup** — arch-diagram·pdf-vision-extract 의존성(python-pptx·pymupdf·plantuml). (의존: python)
66
+ - **motion-graphic-setup** — hyperframes(무료 모션 그래픽 CLI) 전제조건(Node≥22 + ffmpeg → `npx hyperframes`). (`motion-graphic-make` 의존성)
67
+ - **3d-intro-setup** — 3D 인트로용 크레덴셜(Azure gpt-image·Sora-2, 선택 WAN 영상 키 풀)·의존성(Node/ffmpeg) + 무과금 프리플라이트. (`3d-intro-build` 의존성)
68
+
69
+ **권한 (주의, 기본 미선택)**
70
+ - **setup-bypass-permissions** — Claude Code 의 기본 권한 모드를 `bypassPermissions` 로 바꿔 모든 세션에서 도구 실행 확인을 끔.
71
+ - 위 묶음과 섞지 않고 단일 선택 질문 하나로 따로 묻는다(`multiSelect: false`). 선택지는 `넣지 않음 (권장)`, `넣기 (위험)` 순서다.
72
+ - 사용자가 이 항목을 직접 고를 때만 넣는다. "전부" 같은 묶음 선택이나 번호 범위에는 들어가지 않는다.
73
+ - 이 스킬은 모델이 호출할 수 없다(`disable-model-invocation`). `넣기` 를 고르면 실행하지 말고, 사용자에게 `/banker:setup-bypass-permissions on` 을 직접 입력하라고 안내한다. Codex 는 `$banker-setup-bypass-permissions`(플러그인 설치면 `$banker:setup-bypass-permissions`)를 직접 부르라고 안내한다.
74
+ - 입력하면 그 스킬이 위험 경고를 보여 주고 한 번 더 확인받는다. 되돌리기는 `off`.
75
+
76
+ 2. **실행**: 선택된 각 항목을 호출한다(미선택은 건드리지 않음). 단 `setup-bypass-permissions` 는 호출하지 않는다(위 권한 항목의 안내만). Claude Code는 `Skill("banker:<name>")`, **Codex 런타임에선 설치된 `banker-<name>` 스킬(플러그인 설치면 `banker:<name>`)을 적용**한다(예: `Skill("banker:setup-node")`).
77
+ - **의존 순서 강제**: 뒤 계층을 고르면 전제 스킬을 먼저 실행한다 — `setup-lsp` 전에 setup-node·setup-python·setup-java; `setup-mcp` 전에 setup-node·setup-python; `docs-setup` 전에 setup-python. 이미 설치돼 있으면 각 스킬이 감지해 skip(멱등).
78
+ - 각 스킬이 OS를 감지해 알맞은 절차로 설치하고 끝에 검증한다. 한 항목이 실패해도 정직히 보고하고 다음 항목 진행.
79
+
80
+ 3. **마무리 보고(한글)**: 설치된 항목·검증 결과·**재시작/reload 필요 여부**.
81
+ - 플러그인 설치(insane-search)는 `/reload-plugins`(Claude) 또는 재시작 후 반영(Codex는 재시작).
82
+ - MCP 추가(stitch)는 세션 갱신 후 연결 확인 — Claude `claude mcp list`, Codex `codex mcp list`.
83
+
84
+ ## 원칙
85
+ - 각 설치는 **비파괴·멱등**(이미 설치면 skip).
86
+ - 시크릿(API key 등)은 사용자 입력/환경변수로만 — 출력·커밋 금지.
87
+ - root 불가/conda 부재 등은 각 스킬의 폴백 경로로 처리(추정 금지, 감지 기반).
@@ -0,0 +1,29 @@
1
+ {
2
+ "description": "banker hooks for the Codex plugin (codex plugin add banker@banker-plugins), written by scripts/sync-codex-plugin.js. Codex reads this file instead of hooks/hooks.json because .codex-plugin/plugin.json names it. update notice (SessionStart, opt-out BANKER_NO_UPDATE_CHECK), usage counting (Stop, opt-out BANKER_NO_TELEMETRY). The obsidizer hook is installed only by obsidizer --enable. Codex runs them only after you trust them in /hooks, and outside its sandbox: each command runs the node PATH names (a multicall shim such as Volta or mise, or a .cmd shim on Windows: the node binary it names) only when its real path is absolute and outside the temp folder and the session folder (a session in the home folder itself excepted), from the plugin folder, and otherwise says why it skipped. Each command starts with a hash of the hook files (banker-hooks-rev), so new hook code asks for trust again. command is for sh, commandWindows for PowerShell; PLUGIN_ROOT is the installed plugin folder.",
3
+ "hooks": {
4
+ "SessionStart": [
5
+ {
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": ": banker-hooks-rev 625aade934d2; x() { m=$(printf '%s' \"banker hooks skipped: $1\" | command -p tr -d '\\000-\\037\"\\\\'); printf '{\"systemMessage\":\"%s\"}\\n' \"$m\"; exit 0; }; [ -n \"$PLUGIN_ROOT\" ] || x \"PLUGIN_ROOT is not set\"; p=$(pwd -P); [ -n \"$p\" ] && [ \"$p\" != / ] || x \"the session folder is /\"; u=$(cd /tmp 2>/dev/null && pwd -P); t=$(cd \"${TMPDIR:-/tmp}\" 2>/dev/null && pwd -P); h=; case \"$HOME\" in /?*) h=$(cd \"$HOME\" 2>/dev/null && pwd -P);; esac; w() { for z in \"$u\" \"$t\"; do [ -n \"$z\" ] && case \"$1/\" in \"$z\"/*) return 0;; esac; done; [ \"$p\" = \"$h\" ] && return 1; case \"$1/\" in \"$p\"/*) return 0;; esac; return 1; }; n=$(command -v node) || for d in /opt/homebrew/bin /usr/local/bin; do [ -x \"$d/node\" ] && n=$d/node && break; done; [ -n \"$n\" ] || x \"node is not on PATH (a Codex started from the desktop may not have the shell's PATH)\"; case \"$n\" in /*) ;; *) x \"node on PATH is not an absolute path ($n)\";; esac; set -f; o=$IFS; IFS=:; q=; for v in $PATH; do case \"$v\" in /*) ;; *) continue;; esac; y=$(cd \"$v\" 2>/dev/null && pwd -P) || continue; w \"$y\" || q=$q${q:+:}$v; done; IFS=$o; set +f; PATH=${q:-/usr/bin:/bin}; export PATH; cd \"$PLUGIN_ROOT\" || x \"cannot enter the plugin folder\"; rp() { realpath \"$1\" 2>/dev/null || readlink -f \"$1\" 2>/dev/null || { f=$1; i=0; while [ -L \"$f\" ]; do i=$((i+1)); [ \"$i\" -le 40 ] || return 1; l=$(readlink \"$f\") || return 1; case \"$l\" in /*) f=$l;; *) f=${f%/*}/$l;; esac; done; [ -e \"$f\" ] || return 1; d=$(cd -P \"${f%/*}/\" 2>/dev/null && pwd -P) || return 1; printf '%s\\n' \"${d%/}/${f##*/}\"; }; }; r=$(rp \"$n\") || x \"cannot resolve the real path of $n\"; k() { case \"$1\" in /*) ;; *) x \"node path is not absolute ($1)\";; esac; for d in \"$u\" \"$t\"; do [ -n \"$d\" ] && case \"$1\" in \"$d\"/*) x \"node is in a temp folder ($1)\";; esac; done; [ \"$p\" = \"$h\" ] || case \"$1\" in \"$p\"/*) x \"node is in the session folder ($1)\";; esac; }; case \"${r##*/}\" in node) k \"$r\"; e=$r;; *) k \"$n\"; k \"$r\"; e=$(\"$n\" -p 'require(\"fs\").realpathSync(process.execPath)' 2>/dev/null) || x \"the node shim $n did not name its node\"; k \"$e\";; esac; \"$e\" \"$PLUGIN_ROOT/hooks/run.cjs\" \"$PLUGIN_ROOT/hooks/update-notify.mjs\" --codex --plugin",
10
+ "commandWindows": "$null = 'banker-hooks-rev 625aade934d2'; function x($m) { Write-Output (ConvertTo-Json -Compress @{ systemMessage = \"banker hooks skipped: $m\" }); exit 0 }; if (-not $env:PLUGIN_ROOT) { x 'PLUGIN_ROOT is not set' }; function G($p) { try { (Get-Item -LiteralPath $p -Force -ErrorAction Stop).FullName } catch { try { [IO.Path]::GetFullPath($p) } catch { $p } } }; $sb = @{}; foreach ($l in @(& (Join-Path ([Environment]::SystemDirectory) 'subst.exe') 2>$null)) { if ($l -match '^([A-Za-z]:)\\\\: => (.+)$') { $sb[$matches[1].ToUpper()] = $matches[2] } }; function L($p) { if (-not $p) { return '' }; $p = G $p; for ($i = 0; $i -lt 32; $i++) { $d2 = if ($p.Length -ge 2) { $p.Substring(0, 2).ToUpper() } else { '' }; if ($sb.Contains($d2)) { $p = G ($sb[$d2].TrimEnd('\\') + $p.Substring(2)); continue }; $c = $p; $t = $null; while ($c) { $it = Get-Item -LiteralPath $c -Force -ErrorAction SilentlyContinue; if ($it -and $it.LinkType -in 'SymbolicLink', 'Junction' -and @($it.Target)[0]) { $t = [string]@($it.Target)[0]; break }; $c = Split-Path -LiteralPath $c }; if (-not $t) { break }; if (-not [IO.Path]::IsPathRooted($t)) { $t = Join-Path (Split-Path -LiteralPath $c) $t }; $p = G ($t.TrimEnd('\\') + $p.Substring($c.Length)) }; $p.TrimEnd('\\') }; $ds = @($env:TEMP, $env:TMP); if ($env:LOCALAPPDATA) { $ds += \"$env:LOCALAPPDATA\\Temp\" }; $w = L $PWD.Path; if ($w -ne (L $env:USERPROFILE)) { $ds += $w }; $ds = @($ds | Where-Object { $_ } | ForEach-Object { L $_ } | Where-Object { $_ }); function u($f) { $f = L $f; foreach ($d in $ds) { if ($f -eq $d -or $f.StartsWith($d + '\\', 'OrdinalIgnoreCase')) { return $true } }; $false }; function k($f) { if (u $f) { x \"node is in a temp folder or the session folder ($(L $f))\" }; L $f }; $nd = @(@($env:PATH -split ';') | ForEach-Object { [Environment]::ExpandEnvironmentVariables($_.Trim().Trim('\"')) } | Where-Object { $_ -match '^[A-Za-z]:\\\\' -and ([IO.DriveInfo]::new($_.Substring(0, 1))).DriveType -ne 'Network' }); $n = $null; foreach ($d in $nd) { foreach ($e in 'node.exe', 'node.bat', 'node.cmd') { $f = Join-Path $d $e; if (Test-Path -LiteralPath $f -PathType Leaf) { $n = $f; break } }; if ($n) { break } }; if (-not $n) { x 'node is not on PATH' }; $env:PATH = ($nd | Where-Object { -not (u $_) }) -join ';'; $r = k $n; if (-not (Set-Location -LiteralPath $env:PLUGIN_ROOT -PassThru -ErrorAction SilentlyContinue)) { x 'cannot enter the plugin folder' }; if ($r -notmatch '\\.exe$') { $e = & $r -p process.execPath 2>$null | Select-Object -Last 1; if (-not $e -or $e -notmatch '\\.exe$' -or -not (Test-Path -LiteralPath $e -PathType Leaf)) { x \"the node shim $r did not name its node\" }; $r = k $e }; & $r \"$env:PLUGIN_ROOT\\hooks\\run.cjs\" \"$env:PLUGIN_ROOT\\hooks\\update-notify.mjs\" --codex --plugin",
11
+ "timeout": 5
12
+ }
13
+ ]
14
+ }
15
+ ],
16
+ "Stop": [
17
+ {
18
+ "hooks": [
19
+ {
20
+ "type": "command",
21
+ "command": ": banker-hooks-rev 625aade934d2; x() { printf '%s\\n' \"banker hooks skipped: $1\" >&2; exit 0; }; [ -n \"$PLUGIN_ROOT\" ] || x \"PLUGIN_ROOT is not set\"; p=$(pwd -P); [ -n \"$p\" ] && [ \"$p\" != / ] || x \"the session folder is /\"; u=$(cd /tmp 2>/dev/null && pwd -P); t=$(cd \"${TMPDIR:-/tmp}\" 2>/dev/null && pwd -P); h=; case \"$HOME\" in /?*) h=$(cd \"$HOME\" 2>/dev/null && pwd -P);; esac; w() { for z in \"$u\" \"$t\"; do [ -n \"$z\" ] && case \"$1/\" in \"$z\"/*) return 0;; esac; done; [ \"$p\" = \"$h\" ] && return 1; case \"$1/\" in \"$p\"/*) return 0;; esac; return 1; }; n=$(command -v node) || for d in /opt/homebrew/bin /usr/local/bin; do [ -x \"$d/node\" ] && n=$d/node && break; done; [ -n \"$n\" ] || x \"node is not on PATH (a Codex started from the desktop may not have the shell's PATH)\"; case \"$n\" in /*) ;; *) x \"node on PATH is not an absolute path ($n)\";; esac; set -f; o=$IFS; IFS=:; q=; for v in $PATH; do case \"$v\" in /*) ;; *) continue;; esac; y=$(cd \"$v\" 2>/dev/null && pwd -P) || continue; w \"$y\" || q=$q${q:+:}$v; done; IFS=$o; set +f; PATH=${q:-/usr/bin:/bin}; export PATH; cd \"$PLUGIN_ROOT\" || x \"cannot enter the plugin folder\"; rp() { realpath \"$1\" 2>/dev/null || readlink -f \"$1\" 2>/dev/null || { f=$1; i=0; while [ -L \"$f\" ]; do i=$((i+1)); [ \"$i\" -le 40 ] || return 1; l=$(readlink \"$f\") || return 1; case \"$l\" in /*) f=$l;; *) f=${f%/*}/$l;; esac; done; [ -e \"$f\" ] || return 1; d=$(cd -P \"${f%/*}/\" 2>/dev/null && pwd -P) || return 1; printf '%s\\n' \"${d%/}/${f##*/}\"; }; }; r=$(rp \"$n\") || x \"cannot resolve the real path of $n\"; k() { case \"$1\" in /*) ;; *) x \"node path is not absolute ($1)\";; esac; for d in \"$u\" \"$t\"; do [ -n \"$d\" ] && case \"$1\" in \"$d\"/*) x \"node is in a temp folder ($1)\";; esac; done; [ \"$p\" = \"$h\" ] || case \"$1\" in \"$p\"/*) x \"node is in the session folder ($1)\";; esac; }; case \"${r##*/}\" in node) k \"$r\"; e=$r;; *) k \"$n\"; k \"$r\"; e=$(\"$n\" -p 'require(\"fs\").realpathSync(process.execPath)' 2>/dev/null) || x \"the node shim $n did not name its node\"; k \"$e\";; esac; \"$e\" \"$PLUGIN_ROOT/hooks/run.cjs\" \"$PLUGIN_ROOT/hooks/telemetry-count-codex.mjs\"",
22
+ "commandWindows": "$null = 'banker-hooks-rev 625aade934d2'; function x($m) { [Console]::Error.WriteLine(\"banker hooks skipped: $m\"); exit 0 }; if (-not $env:PLUGIN_ROOT) { x 'PLUGIN_ROOT is not set' }; function G($p) { try { (Get-Item -LiteralPath $p -Force -ErrorAction Stop).FullName } catch { try { [IO.Path]::GetFullPath($p) } catch { $p } } }; $sb = @{}; foreach ($l in @(& (Join-Path ([Environment]::SystemDirectory) 'subst.exe') 2>$null)) { if ($l -match '^([A-Za-z]:)\\\\: => (.+)$') { $sb[$matches[1].ToUpper()] = $matches[2] } }; function L($p) { if (-not $p) { return '' }; $p = G $p; for ($i = 0; $i -lt 32; $i++) { $d2 = if ($p.Length -ge 2) { $p.Substring(0, 2).ToUpper() } else { '' }; if ($sb.Contains($d2)) { $p = G ($sb[$d2].TrimEnd('\\') + $p.Substring(2)); continue }; $c = $p; $t = $null; while ($c) { $it = Get-Item -LiteralPath $c -Force -ErrorAction SilentlyContinue; if ($it -and $it.LinkType -in 'SymbolicLink', 'Junction' -and @($it.Target)[0]) { $t = [string]@($it.Target)[0]; break }; $c = Split-Path -LiteralPath $c }; if (-not $t) { break }; if (-not [IO.Path]::IsPathRooted($t)) { $t = Join-Path (Split-Path -LiteralPath $c) $t }; $p = G ($t.TrimEnd('\\') + $p.Substring($c.Length)) }; $p.TrimEnd('\\') }; $ds = @($env:TEMP, $env:TMP); if ($env:LOCALAPPDATA) { $ds += \"$env:LOCALAPPDATA\\Temp\" }; $w = L $PWD.Path; if ($w -ne (L $env:USERPROFILE)) { $ds += $w }; $ds = @($ds | Where-Object { $_ } | ForEach-Object { L $_ } | Where-Object { $_ }); function u($f) { $f = L $f; foreach ($d in $ds) { if ($f -eq $d -or $f.StartsWith($d + '\\', 'OrdinalIgnoreCase')) { return $true } }; $false }; function k($f) { if (u $f) { x \"node is in a temp folder or the session folder ($(L $f))\" }; L $f }; $nd = @(@($env:PATH -split ';') | ForEach-Object { [Environment]::ExpandEnvironmentVariables($_.Trim().Trim('\"')) } | Where-Object { $_ -match '^[A-Za-z]:\\\\' -and ([IO.DriveInfo]::new($_.Substring(0, 1))).DriveType -ne 'Network' }); $n = $null; foreach ($d in $nd) { foreach ($e in 'node.exe', 'node.bat', 'node.cmd') { $f = Join-Path $d $e; if (Test-Path -LiteralPath $f -PathType Leaf) { $n = $f; break } }; if ($n) { break } }; if (-not $n) { x 'node is not on PATH' }; $env:PATH = ($nd | Where-Object { -not (u $_) }) -join ';'; $r = k $n; if (-not (Set-Location -LiteralPath $env:PLUGIN_ROOT -PassThru -ErrorAction SilentlyContinue)) { x 'cannot enter the plugin folder' }; if ($r -notmatch '\\.exe$') { $e = & $r -p process.execPath 2>$null | Select-Object -Last 1; if (-not $e -or $e -notmatch '\\.exe$' -or -not (Test-Path -LiteralPath $e -PathType Leaf)) { x \"the node shim $r did not name its node\" }; $r = k $e }; & $r \"$env:PLUGIN_ROOT\\hooks\\run.cjs\" \"$env:PLUGIN_ROOT\\hooks\\telemetry-count-codex.mjs\"",
23
+ "timeout": 5
24
+ }
25
+ ]
26
+ }
27
+ ]
28
+ }
29
+ }
@@ -2,17 +2,17 @@
2
2
  "version": 1,
3
3
  "note": "Per-surface target manifest for banker multi-tool distribution. Enumerate skills by SKILL.md presence (excludes ultra-init-workspace). target=both -> install to Claude Code AND Codex; claude-only -> Claude Code only. The Codex generator (codex/generate) reads this.",
4
4
  "surfaces": [
5
- { "name": "append_wiki", "type": "skill", "target": "both", "reason": "knowledge capture; tool-agnostic workflow", "supportingFiles": [], "caveat": "uses wiki_* MCP (OMC/OMX) at runtime; copies fine, needs a wiki MCP present" },
5
+ { "name": "append_wiki", "type": "skill", "target": "both", "reason": "knowledge capture; tool-agnostic workflow", "supportingFiles": [], "caveat": "Claude Code uses the OMC wiki_* MCP over .omc/wiki; Codex has no wiki MCP and uses the omx wiki CLI over omx_wiki/ (same tool names and inputs), which writes inside the workspace only" },
6
6
  { "name": "arch-diagram", "type": "skill", "target": "both", "reason": "PlantUML+pptx diagramming; tool-agnostic", "supportingFiles": ["build_pptx_template.py"] },
7
7
  { "name": "vertical-pptx", "type": "skill", "target": "both", "reason": "A4 portrait (210x297mm) pptx spec: build, verify, repair, and 16:9 conversion; tool-agnostic", "supportingFiles": ["build_a4p.js", "build_a4p.py", "verify_a4p.mjs"], "caveat": "owns the spec only and delegates layout/color/charts to a pptx document skill when one is reachable, falling back to a minimal self-contained block otherwise; the verify path needs node, and building needs pptxgenjs or python-pptx which it never auto-installs (points at vertical-pptx-setup instead)" },
8
8
  { "name": "vertical-pptx-setup", "type": "skill", "target": "both", "reason": "installs what vertical-pptx runs on (pptxgenjs or python-pptx) plus optional LibreOffice for PDF render checks; OS and privilege adaptive", "supportingFiles": [], "caveat": "LibreOffice is optional and only buys visual/PDF confirmation; without root it extracts to a home prefix, and on RHEL8/Rocky8 the distro build is required because upstream 26.x needs a newer glibc than 2.28" },
9
9
  { "name": "audit-mock", "type": "skill", "target": "both", "reason": "static anti-pattern audit; tool-agnostic", "supportingFiles": [] },
10
10
  { "name": "audit-security", "type": "skill", "target": "both", "reason": "SCA/SAST/secrets methodology; tool-agnostic", "supportingFiles": [] },
11
11
  { "name": "audit-web-page", "type": "skill", "target": "both", "reason": "playwright live page audit; tool-agnostic", "supportingFiles": ["harness.py"], "caveat": "needs playwright (setup-playwright)" },
12
- { "name": "compact-wiki", "type": "skill", "target": "both", "reason": "wiki dedup/merge; tool-agnostic workflow", "supportingFiles": [], "caveat": "uses wiki_* MCP at runtime" },
12
+ { "name": "compact-wiki", "type": "skill", "target": "both", "reason": "wiki dedup/merge; tool-agnostic workflow", "supportingFiles": [], "caveat": "Claude Code uses the OMC wiki_* MCP over .omc/wiki; Codex uses the omx wiki CLI over omx_wiki/ (no wiki MCP on Codex); the snapshot is omx_wiki.bak-<time> there" },
13
13
  { "name": "play-qa", "type": "skill", "target": "both", "reason": "Godot HTML5 in-browser QA; tool-agnostic", "supportingFiles": [], "caveat": "needs playwright (setup-playwright)" },
14
14
  { "name": "humanizer", "type": "skill", "target": "both", "reason": "AI-writing cleanup; tool-agnostic (vendored MIT)", "supportingFiles": ["LICENSE", "README.md", "AGENTS.md"] },
15
- { "name": "lineage", "type": "skill", "target": "both", "reason": "session->HTML export; the default flow has session-model reviewers (Claude=Plan without a model, Codex=spawn_agent without a role) judge noise and write one-line summaries from a redacted review pack; --rulebase is the rules-only one-pass run; reads Claude Code transcripts only", "supportingFiles": ["lineage.py"] },
15
+ { "name": "lineage", "type": "skill", "target": "both", "reason": "session->HTML export; the default flow has session-model reviewers (Claude=Plan without a model, Codex=spawn_agent without a role) judge noise and write one-line summaries from a redacted review pack; --rulebase is the rules-only one-pass run; reads Claude Code transcripts and Codex rollouts", "supportingFiles": ["lineage.py"], "caveat": "inside Codex the session is found by CODEX_THREAD_ID (the id at the end of the rollout file name) under $CODEX_HOME/sessions, and --all-sessions takes the rollouts whose session_meta cwd is this folder; from a rollout it reads what the user typed (user_message), what the model said (agent_message) and tool call names (response_item *_call), not the model input, reasoning or tool output; under workspace-write the reviewer-decision cache in ~/.cache/lineage is not written (one WARN) unless the apply step runs with approval or Codex starts with --add-dir ~/.cache/lineage" },
16
16
  { "name": "make-notion-guide", "type": "skill", "target": "both", "reason": "API guide authoring; tool-agnostic", "supportingFiles": [] },
17
17
  { "name": "nothing-design", "type": "skill", "target": "both", "reason": "UI design system; tool-agnostic", "supportingFiles": ["references/components.md", "references/platform-mapping.md", "references/tokens.md"] },
18
18
  { "name": "pdf-vision-extract", "type": "skill", "target": "both", "reason": "PDF->PNG for vision; tool-agnostic", "supportingFiles": [] },
@@ -28,7 +28,7 @@
28
28
  { "name": "ultra-init", "type": "skill", "target": "both", "reason": "orchestrates ralplan->ralph->QA gate (no ultragoal ledger: OMC 5.6.1 checkpoints need a /goal snapshot that would compete with ralph); Claude=OMC 5 (verify cycle in place of the removed ultraqa; needs the omc CLI with `omc ralph verify`), Codex=OMX (OMX ultraqa); body runtime-aware", "supportingFiles": [] },
29
29
  { "name": "omc-reference", "type": "skill", "target": "both", "reason": "OMC/OMX agent/tool/skill registry reference; runtime-aware (Codex counterpart is OMX)", "supportingFiles": [] },
30
30
  { "name": "setup-omc", "type": "skill", "target": "both", "reason": "installs OMC (Claude) or OMX (Codex `omx setup`); body already dual-runtime", "supportingFiles": [] },
31
- { "name": "setup-omc-hud", "type": "skill", "target": "both", "reason": "installs the omc_hud statusline wrapper v4 (Claude statusLine) from files bundled in assets/, offline and with one node command on every OS, then turns payload-mon on for the PL segment; off/status handle the update-notice block older wrappers took; Codex uses OMX `hud`; runtime-aware", "supportingFiles": ["assets/apply-hud.mjs", "assets/omc-hud-custom.mjs", "assets/hud-config.json", "assets/LICENSE-omc_hud", "scripts/claude-update-last.mjs"] },
31
+ { "name": "setup-omc-hud", "type": "skill", "target": "both", "reason": "installs the omc_hud statusline wrapper v4 (Claude statusLine) from files bundled in assets/, offline and with one node command on every OS, then turns payload-mon on for the PL segment; off/status handle the update-notice block older wrappers took; Codex target sets the TUI [tui] status_line to an OMX preset (assets/codex-status-line.mjs) only when none is set and removes only its own; runtime-aware", "supportingFiles": ["assets/apply-hud.mjs", "assets/codex-status-line.mjs", "assets/codex-config.mjs", "assets/omc-hud-custom.mjs", "assets/hud-config.json", "assets/LICENSE-omc_hud", "scripts/claude-update-last.mjs"], "caveat": "the target is the Claude Code statusLine; run from Codex with no target named, it asks first (Codex's own status line is [tui] status_line) and installs nothing when it cannot ask; the Claude Code install writes ~/.claude, so under workspace-write apply-hud and payload-mon on need approval to run outside it (not --add-dir ~/.claude); omx hud --tmux splits the current tmux window" },
32
32
  { "name": "setup-stitch", "type": "skill", "target": "both", "reason": "registers the Stitch MCP proxy (RockyLinux8 ~/bin/stitch-proxy.sh); Claude `claude mcp add`, Codex `codex mcp add`", "supportingFiles": [] },
33
33
 
34
34
  { "name": "docs-setup", "type": "skill", "target": "both", "reason": "installs arch-diagram/pdf-vision-extract deps (python-pptx, pymupdf, plantuml); python-env detect/select; runtime-agnostic installer", "supportingFiles": [] },
@@ -36,8 +36,9 @@
36
36
  { "name": "curation", "type": "skill", "target": "both", "reason": "decision-framing behavior (options/rec/confidence + --perf); no runtime deps; identical in both", "supportingFiles": [] },
37
37
  { "name": "deep-init", "type": "skill", "target": "both", "reason": "hierarchical AGENTS.md generation (port of OMC deepinit); runtime-agnostic fs+doc; subagents Claude=OMC/Codex=OMX", "supportingFiles": [] },
38
38
  { "name": "deep-research", "type": "skill", "target": "both", "reason": "fan-out + adversarial-verify web research (re-authored from bundled workflow); Claude WebSearch/Workflow, Codex OMX autoresearch; runtime-aware", "supportingFiles": [] },
39
+ { "name": "lfm", "type": "skill", "target": "both", "reason": "learn from master: researches how the top expert groups of a field actually work (steps, roles, quality bars, review, tools, failures and fixes) from the primary material they publish, separates shared from group-specific practice, and turns each into a plan item (M-n: apply, adapt, drop with a reason); ultra-interview, ultra-chain, deep-research and rfp-author call it in their research step; tool-agnostic (runtime web search and fetch)", "supportingFiles": [], "caveat": "needs a web search tool; with none or no network it ends with \"웹 조사 불가\" and writes no table from model knowledge; called by another skill it gets --no-questions" },
39
40
  { "name": "ralph-qa", "type": "skill", "target": "both", "reason": "independent verify loop (ralplan+critic logic): a backbone of 3+ reviewer agents on the session model always runs (Claude=Plan without a model, Codex=spawn_agent without a role or forked context; read-only by instruction); --codex/--gemini/--opencode seat that CLI's best model (asks when ambiguous, configured default when nobody can be asked), a node runner (references/seat-run.mjs) makes the private folders and the payload (a diff that carries the listed new files, made through a copy of the index), scans it, sends each seat from its own copy with answers kept elsewhere under a 600 s limit that ends the seat's whole process group, and cleans up (codex read-only with its shell tool, exec-policy rules, MCP servers, sub-agents, hooks, notify, web search, metrics and OpenTelemetry off, not seated when a managed config or a requirements file overrides those; gemini under a deny-all admin policy that a helper checks first, with no MCP servers, extensions or prompt telemetry, its error reports kept in the answer folder, and its session records removed after, those of runs cut short too; opencode as a per-run deny-all agent reading the payload on stdin, auto-compaction off). Seat-lifecycle monotone gate (INCONCLUSIVE on seat loss); runtime-aware", "supportingFiles": ["references/verifier-probe.mjs", "references/payload-scan.mjs", "references/gemini-read-only.toml", "references/gemini-seat.mjs", "references/seat-run.mjs", "references/seat-payload.mjs", "references/seat-spawn.mjs"] },
40
- { "name": "smart-compact", "type": "skill", "target": "both", "reason": "context-threshold compaction-hygiene gate (statusLine detect + hook bridge + assistant chain + TUI handoff); runtime-aware", "supportingFiles": [] },
41
+ { "name": "smart-compact", "type": "skill", "target": "both", "reason": "context-threshold compaction-hygiene gate (statusLine detect + hook bridge + assistant chain + TUI handoff); runtime-aware", "supportingFiles": ["scripts/codex-gate.mjs"], "caveat": "Claude Code detects through a statusLine wrapper; Codex through scripts/codex-gate.mjs: on copies it to $CODEX_HOME/hooks-custom/banker-smart-compact-gate.mjs (out of any workspace, since Codex runs trusted hooks outside the sandbox) and appends a UserPromptSubmit group for it last in hooks.json (PowerShell call form on Windows); the hook reads the rollout's last token_count (last_token_usage over model_context_window). Codex runs it only after the user trusts it (Hooks need review, /hooks); on/off write ~/.codex, so under workspace-write they need approval to run outside the sandbox (not --add-dir ~/.codex); run off before removing banker or OMX" },
41
42
  { "name": "visual-ralph", "type": "skill", "target": "both", "reason": "measured visual build loop (port of OMX visual-ralph); Claude ralph+visual-verdict+Stitch imagegen, Codex $ralph+$imagegen; runtime-aware", "supportingFiles": [] },
42
43
 
43
44
  { "name": "setup-node", "type": "skill", "target": "both", "reason": "installs nvm+Node22 (or winget/nvm-windows) per-OS; prerequisite for npx MCP servers + Codex/OMX tooling; runtime-agnostic installer", "supportingFiles": [] },
@@ -47,11 +48,11 @@
47
48
  { "name": "setup-tmux", "type": "skill", "target": "both", "reason": "installs tmux per-OS (Rocky8 3.6a source-build, apt/brew, Windows psmux); OMC team/worktree + OMX $team/HUD require it", "supportingFiles": [] },
48
49
  { "name": "setup-pwsh", "type": "skill", "target": "both", "reason": "Windows PowerShell 7 env (Terminal/Git/$PROFILE UTF-8); Claude CLAUDE_CODE_GIT_BASH_PATH, Codex native shell; no-op off-Windows", "supportingFiles": [] },
49
50
  { "name": "setup-mcp", "type": "skill", "target": "both", "reason": "installs common standalone MCP servers (context7/seq-thinking/filesystem/git/fetch); Claude `claude mcp add`, Codex config.toml [mcp_servers.*]; needs setup-node/python", "supportingFiles": [] },
50
- { "name": "setup-bypass-permissions", "type": "skill", "target": "both", "reason": "opt-in, typed by the person only (disable-model-invocation; Codex agents/openai.yaml allow_implicit_invocation: false): sets Claude Code permissions.defaultMode to bypassPermissions after a risk warning and an explicit confirmation; node script first, python3/PowerShell fallback when node cannot run, a command the person runs when the account may not write; off restores; Codex leaves its own approval policy alone", "supportingFiles": ["scripts/bypass-permissions.mjs", "scripts/fallback/bypass-permissions.py", "scripts/fallback/bypass-permissions.ps1", "agents/openai.yaml"] },
51
+ { "name": "setup-bypass-permissions", "type": "skill", "target": "both", "reason": "opt-in, typed by the person only (disable-model-invocation; Codex agents/openai.yaml allow_implicit_invocation: false): sets Claude Code permissions.defaultMode to bypassPermissions after a risk warning and an explicit confirmation; node script first, python3/PowerShell fallback when node cannot run, a command the person runs when the account may not write; off restores; target codex sets top-level approval_policy = \"never\" and sandbox_mode = \"danger-full-access\" in $CODEX_HOME/config.toml (scripts/codex-bypass.mjs, records the values before for off, refuses when /etc/codex requirements do not allow them)", "supportingFiles": ["scripts/bypass-permissions.mjs", "scripts/codex-bypass.mjs", "scripts/codex-config.mjs", "scripts/fallback/bypass-permissions.py", "scripts/fallback/bypass-permissions.ps1", "agents/openai.yaml"] },
51
52
  { "name": "setup-sandbox", "type": "skill", "target": "both", "reason": "agent sandbox per-OS (bubblewrap+userns / AppContainer / Seatbelt) + rust/cargo + git safe.directory; Codex sandbox_mode", "supportingFiles": [] },
52
53
  { "name": "setup-harness-factory","type": "skill", "target": "both", "reason": "installs+configures+guides the revfactory/harness team-architecture factory plugin (Claude harness@harness-marketplace, Codex SaehwanPark/meta-harness); Apache-2.0 referenced not redistributed", "supportingFiles": [] },
53
54
 
54
- { "name": "obsidizer", "type": "skill", "target": "both", "reason": "AI-wiki -> Obsidian graph normalize/interlink; LLM semantic edits + zero-input deterministic canonicalizer, runtime-agnostic; in-place durable", "supportingFiles": ["obsidize.mjs"], "caveat": "OMC-managed trees: 9-field frontmatter envelope + reserved files + no-rename + bare [[slug]] links only (extractWikiLinks slugifies piped/heading forms -> broken-ref); aliases written in generic vaults only; Canvas sidecars and body-inline :: are durable in-place; uses wiki_lint read-only. --enable is Claude-only (Codex has no MCP tool hooks) and is an honest no-op on Codex." },
55
+ { "name": "obsidizer", "type": "skill", "target": "both", "reason": "AI-wiki -> Obsidian graph normalize/interlink; LLM semantic edits + zero-input deterministic canonicalizer, runtime-agnostic; in-place durable", "supportingFiles": ["obsidize.mjs"], "caveat": "OMC-managed trees: 9-field frontmatter envelope + reserved files + no-rename + bare [[slug]] links only (extractWikiLinks slugifies piped/heading forms -> broken-ref); aliases written in generic vaults only; Canvas sidecars and body-inline :: are durable in-place; uses wiki_lint read-only. On Codex (no wiki MCP) --enable writes omx_wiki/.obsidizer and installs a user-scope PostToolUse hook (matcher Bash, `banker hooks enable obsidize`) that canonicalizes only after an `omx wiki` ingest/add shell call, using the pages that call's JSON names; that install writes ~/.codex, so under workspace-write it needs approval to run outside the sandbox (not --add-dir ~/.codex), and Codex runs the hook only after the user trusts it (Hooks need review, /hooks)." },
55
56
 
56
57
  { "name": "ultra-interview", "type": "skill", "target": "both", "reason": "research-first interview that resolves what public sources can answer and asks the human only what they alone can decide; discrete checklist gate (unresolved/total) instead of a scalar self-score", "supportingFiles": [], "caveat": "does NOT bundle or replace the OMC/OMX native deep-interview. Owns its own rubric on purpose: OMC scores 3 dimensions and OMX scores 5, so inheriting a native score would make the same threshold mean different things per runtime. Regulatory lookup is a general 'find the jurisdiction's primary source' instruction, not a hardcoded endpoint." },
57
58
  { "name": "interval-report", "type": "skill", "target": "both", "reason": "human-facing progress ledger at docs/intermission.md for long runs; thin time layer + renderer over whatever state exists", "supportingFiles": [], "caveat": "start time is persisted in the file and never re-stamped (a compaction/resume re-stamp collapses elapsed to 0 and biases the report optimistic exactly when it matters most). Wall-clock comes from `date` because neither runtime exposes hour:minute in context. Reads ultragoal state when present but never duplicates it; leaves compaction triggering to smart-compact." },
@@ -64,9 +65,9 @@
64
65
  { "name": "motion-graphic-make", "type": "skill", "target": "both", "reason": "thin wrapper delegating to hyperframes /motion-graphics (free form categories); owns no render pipeline, only the stage gates (plan approval, snapshot and render review, independent check) and the review page and preview server it shares with 3d-intro-build; runtime-agnostic", "supportingFiles": ["references/preview-lib.mjs", "references/serve.mjs", "references/curate.mjs"], "caveat": "needs hyperframes via motion-graphic-setup (npx, Apache-2.0); the three references are byte-identical copies of 3d-intro-build's (scripts/sync-adapter.js)" },
65
66
  { "name": "3d-intro-setup", "type": "skill", "target": "both", "reason": "collects Azure creds (direct or console-sample parse) to untracked env + FREE preflight; installs Node/ffmpeg; runtime-agnostic", "supportingFiles": ["references/azure-adapter.mjs", "references/video-pool.mjs"] },
66
67
  { "name": "3d-intro-build", "type": "skill", "target": "both", "reason": "scroll-scrub 3D intro: gpt-image stills, WAN key pool video with Sora-2 fallback (forward-chaining, or the optional hold-and-flight mode), a review page for every paid stage, a page with no inline script or style (strict CSP), optional scene-by-scene navigation and glass panel, and a Playwright measurement for the independent check; vendored scroll-world engine (MIT) left unmodified; cross-platform Node", "supportingFiles": ["references/azure-adapter.mjs", "references/video-pool.mjs", "references/scrub-engine.js", "references/index-template.html", "references/prompts.md", "references/LICENSE", "references/NOTICE.md", "references/preview-lib.mjs", "references/serve.mjs", "references/assemble.mjs", "references/curate.mjs", "references/intro-fixes.css", "references/panel-glass.css", "references/step-nav.js", "references/step-nav.css", "references/verify-intro.mjs", "references/verify.md"], "caveat": "the independent check (verify-intro.mjs) needs Node Playwright with Chromium (setup-playwright); the hold-and-flight mode needs WAN keys and is not yet confirmed by a paid smoke" },
67
- { "name": "payload-mon", "type": "skill", "target": "both", "reason": "toggles an estimated API request payload segment (bytes against Claude Code's 32MB request limit) in the OMC custom HUD statusline, beside ctx; pure Node, no deps", "supportingFiles": ["scripts/payload-mon.mjs", "scripts/payload-size.mjs"], "caveat": "measures Claude Code sessions only (the 32MB limit and the transcript format are Claude Code's); run from Codex it still manages the same machine's Claude Code HUD wrapper but never measures Codex's own requests. Needs the OMC custom HUD wrapper (setup-omc-hud); the wrapper imports a module copy kept beside it because plugin install paths are versioned and retired on update" },
68
+ { "name": "payload-mon", "type": "skill", "target": "both", "reason": "toggles an estimated API request payload segment (bytes against Claude Code's 32MB request limit) in the OMC custom HUD statusline, beside ctx; pure Node, no deps", "supportingFiles": ["scripts/payload-mon.mjs", "scripts/payload-size.mjs"], "caveat": "measures Claude Code sessions only (the 32MB limit and the transcript format are Claude Code's); run from Codex it still manages the same machine's Claude Code HUD wrapper but never measures Codex's own requests. Under Codex's workspace-write sandbox, on and off need approval to run outside it (not --add-dir ~/.claude, which would let the session rewrite hooks); status only reads. Needs the OMC custom HUD wrapper (setup-omc-hud); the wrapper imports a module copy kept beside it because plugin install paths are versioned and retired on update" },
68
69
  { "name": "tone-compact", "type": "skill", "target": "both", "reason": "turns compact Korean writing rules (ASD-STE100 based: lists and tables, transliterated terms, no decorative symbols) on or off across sessions; pure Node, no deps", "supportingFiles": ["scripts/tone-compact.mjs", "scripts/instruction-toggle.mjs"], "caveat": "per runtime: Claude Code gets <config>/rules/banker-tone-compact.md; Codex gets one marked block at the end of $CODEX_HOME/AGENTS.override.md (when it has content of its own) or AGENTS.md, wrapped in USER:OMX:POLICY so omx setup --merge-agents and a plain omx setup with team mode on keep it (--force, a confirmed overwrite or a plain omx setup with team mode off replace the file; run on again). Turning it on in one runtime leaves the other as it is" },
69
- { "name": "omc-patch", "type": "skill", "target": "both", "reason": "re-applies local OMC hook patches after an OMC auto-update and pins the OMC marketplace origin; finds a timeout helper an older kit left inside a block (hooks such as project-memory silently off) and fixes it by reverting the active folder and patching again; probes the project-memory hook in a scratch project; pure Node, no deps", "supportingFiles": ["scripts/omc-patch.mjs", "scripts/probe-pm.mjs"], "caveat": "acts on the Claude Code OMC plugin cache under ~/.claude even when run from Codex; TARGET_VERSION 5.7.0 is hard-coded in the tool and only a plain apply uses it; the skill passes --no-update on every apply and check; --root touches one plugin folder only and never the marketplace pin" },
70
+ { "name": "omc-patch", "type": "skill", "target": "both", "reason": "re-applies local OMC hook patches after an OMC auto-update and pins the OMC marketplace origin; finds a timeout helper an older kit left inside a block (hooks such as project-memory silently off) and fixes it by reverting the active folder and patching again; probes the project-memory hook in a scratch project; pure Node, no deps", "supportingFiles": ["scripts/omc-patch.mjs", "scripts/probe-pm.mjs"], "caveat": "acts on the Claude Code OMC plugin cache under ~/.claude even when run from Codex; under Codex's workspace-write sandbox --check and probe-pm run as they are, while apply and revert need approval to run outside it (not --add-dir ~/.claude); TARGET_VERSION 5.7.0 is hard-coded in the tool and only a plain apply uses it; the skill passes --no-update on every apply and check; --root touches one plugin folder only and never the marketplace pin" },
70
71
  { "name": "remains", "type": "skill", "target": "both", "reason": "finds remaining bugs, defects and unverified items and shows them in one table; runs the project's tests on registered SSH test boxes; pure Node, no deps", "supportingFiles": ["scripts/boxes.mjs"], "caveat": "box runs need ssh, scp and git on this machine and key-only SSH logins; boxes are registered in ~/.config/banker/test-boxes.json; read and test only, never fixes or pushes" },
71
72
  { "name": "trouble-shooting", "type": "skill", "target": "both", "reason": "investigates a problem and reports symptom, problem, cause, fix and action plan in one table, one row per problem; --no-plan stops at the fix; report only, never fixes", "supportingFiles": [] },
72
73
  { "name": "ultra-chain", "type": "skill", "target": "both", "reason": "orchestrates nine stages in order: deep-research, ultra-interview, ralplan --deliberate followed by a ralph-qa plan quorum of 3+ reviewers (ralplan has two reviewers and no way to add more), a mock the user approves, ralph --critic=critic (Codex: OMX ralph plus a critic loop, since OMX ralph has no --critic), tests on the registered OS boxes fed to a ralph-qa quorum, visual review (machine diff against the mock, screenshots, an independent verdict), a process report rendered from its own ledger, and local sharing; Claude=OMC 5, Codex=OMX; body runtime-aware; pure Node helpers, no deps", "supportingFiles": ["references/chain-ledger.mjs", "references/chain-report.mjs", "references/capture.mjs", "references/serve.mjs", "references/preview-lib.mjs"], "caveat": "uses the sibling banker skills deep-research, ultra-interview, ralph-qa and remains (boxes.mjs); box runs need ssh, scp and git with key-only logins in ~/.config/banker/test-boxes.json; screenshots need Playwright with Chromium; serve.mjs and preview-lib.mjs are byte-identical copies of 3d-intro-build's (scripts/sync-adapter.js); never pushes, opens a PR or posts outside without an explicit request" },
@@ -74,6 +75,8 @@
74
75
  { "name": "theme-selection", "type": "skill", "target": "both", "reason": "applies 74 themes to a project as CSS custom properties, light and dark (148 combinations), with contrast correction; also emits a theme picker (markup and two scripts) and a contrast audit (check), and reads the project's DESIGN.md as more themes; pure Node, no deps, no network", "supportingFiles": ["scripts/themes.mjs", "assets/palettes.json", "assets/LICENSE", "assets/NOTICE.md", "references/integrate.md", "references/contrast.md"], "caveat": "the bundled palettes derive from VoltAgent/awesome-design-md (MIT; LICENSE and NOTICE.md in assets/); theme names only point at the sites the designs reference, and the trademarks belong to their owners; --out overwrites the file it names (refused when that file itself is a symbolic link), so the skill asks first when that file exists" },
75
76
 
76
77
  { "name": "front-qa", "type": "command", "target": "both", "reason": "ralplan->ralph frontend-QA pipeline; Claude=OMC, Codex=OMX", "supportingFiles": [] },
77
- { "name": "setup", "type": "command", "target": "both", "reason": "installer orchestrator; Claude AskUserQuestion multi-select, Codex prompt-based selection", "supportingFiles": [] }
78
+ { "name": "setup", "type": "command", "target": "both", "reason": "installer orchestrator; Claude AskUserQuestion multi-select, Codex prompt-based selection", "supportingFiles": [] },
79
+ { "name": "graceful-pause", "type": "skill", "target": "codex-only", "reason": "Codex counterpart of the Claude Code /graceful-pause mod: sent mid-turn, Codex holds it until the running tool call ends and puts it into the same turn, so the session stops after the current step", "supportingFiles": [], "caveat": "source in codex/skills/graceful-pause (the Claude plugin keeps its immediate /graceful-pause mod); relies on Codex steering a message typed while a turn runs (Codex 0.144.5: delivered after the next tool call)" },
80
+ { "name": "progress", "type": "skill", "target": "codex-only", "reason": "Codex counterpart of the Claude Code /progress mod: reads this session's rollout (found by CODEX_THREAD_ID) and prints the last plan file the session wrote or read as a tree (the same progress-plan.mjs engine, a byte-identical copy kept by scripts/sync-adapter.js), the last update_plan steps (or the requests) and the recent tool calls under the step in progress", "supportingFiles": ["scripts/progress.mjs", "scripts/progress-plan.mjs"], "caveat": "source in codex/skills/progress; not a live panel, it shows the state when called; --pane opens a tmux side pane that redraws every 2 s and --pane off closes it; inside the workspace-write sandbox tmux may be unreachable, so that one command needs approval to run outside it (or the user runs it with !); the rollout is read from its last 32 MB" }
78
81
  ]
79
82
  }
@@ -0,0 +1,30 @@
1
+ ---
2
+ name: graceful-pause
3
+ description: "Codex 에서 작업 중에 보내면 지금 하던 단계만 끝내고 멈춘 뒤 보고하고 지시를 기다림. 작업이 도는 동안 입력창에 `$banker-graceful-pause`(플러그인 설치면 `$banker:graceful-pause`)를 쓰고 Enter 하면, 실행 중인 도구 호출이 끝난 뒤 그 턴에 전달됨. 'graceful-pause'/'멈춰'/'지금 단계만 끝내고 멈춤' 시 사용."
4
+ ---
5
+
6
+ # graceful-pause (Codex)
7
+
8
+ Claude Code 의 `/graceful-pause` 에 해당하는 Codex 스킬이다. 답변은 한글.
9
+
10
+ Codex 는 작업 중에 Enter 로 보낸 글을 "Messages to be submitted after next tool call" 로 보관했다가, 실행 중인 도구 호출이 끝나면 같은 턴에 넣는다.
11
+ 이 스킬을 그렇게 보내면 지금 단계가 끝난 자리에서 멈춘다(Codex 0.144.5 실측: `sleep 40` 이 끝난 뒤 남은 명령을 실행하지 않고 멈춤).
12
+
13
+ ## 이 스킬을 받으면
14
+
15
+ 1. 방금 끝난 도구 호출의 결과를 확인한다. 그 호출은 이미 끝난 상태로 전달된다.
16
+ 2. 남은 단계를 시작하지 않는다. 새 도구 호출, 파일 수정, 명령 실행, 하위 에이전트를 시작하지 않는다.
17
+ 3. 아래를 짧게 보고하고 사용자 지시를 기다린다.
18
+ - 지금까지 한 일
19
+ - 멈춘 지점(마지막으로 끝난 단계)
20
+ - 남은 단계
21
+ 4. 멈춘 자리가 일관되지 않으면(파일을 반쯤 고친 상태, 시작만 한 백그라운드 작업) 그 사실을 보고에 적는다. 되돌리거나 마저 하지 않는다.
22
+ 5. 스킬 뒤에 새 지시가 붙어 있으면 멈춘 다음 그 지시를 따른다.
23
+
24
+ ## 사용자가 쓰는 법
25
+
26
+ - 작업이 도는 동안 입력창에 `$banker-graceful-pause` 를 쓰고 Enter 한다. Codex 플러그인으로 설치했으면 `$banker:graceful-pause` 다. 새 지시를 뒤에 붙여도 된다.
27
+ - 지금 도구 호출까지 바로 끊으려면 Esc 를 누른다. 그때는 이 스킬이 필요 없다.
28
+ - 작업이 없을 때 쓰면 멈출 작업이 없다고 답한다.
29
+ - 스킬 이름을 치면 자동 완성 창이 뜬다. 첫 Enter 는 그 선택이고, 둘째 Enter 가 보낸다. 보낸 글은 입력창 위에
30
+ "Messages to be submitted after next tool call" 아래로 옮겨진다. 입력창에 글이 남아 있으면 Enter 를 한 번 더 누른다.
@@ -0,0 +1,42 @@
1
+ ---
2
+ name: progress
3
+ description: "Codex 에서 지금 세션의 진행 상황을 텍스트 트리로 보임. 맨 위는 이 세션이 쓰거나 읽은 마지막 계획 파일의 트리, 그 아래는 update_plan 단계(없으면 요청)와 진행 중인 단계의 최근 도구 호출. tmux 안이면 `--pane` 으로 오른쪽 칸에 2초마다 갱신. 'progress'/'진행 상황'/'어디까지 했어' 시 사용."
4
+ ---
5
+
6
+ # progress (Codex)
7
+
8
+ Claude Code 의 `/progress` 패널에 해당하는 Codex 스킬이다. 답변은 한글.
9
+
10
+ Codex 에는 Claude Code 의 mod 같은 상시 패널이 없다.
11
+ 그래서 이 스킬은 부를 때마다 지금 세션의 기록(rollout)을 읽어 한 번 보여 준다.
12
+ tmux 안이면 오른쪽 칸을 열어 계속 갱신할 수 있다.
13
+
14
+ ## 보이는 것
15
+
16
+ - 계획: 이 세션이 도구 호출로 쓰거나 읽은 마지막 계획 파일의 트리. 제목 아래 체크 수(`1/2`)와 체크박스(`[x]`, `[ ]`)를 보인다.
17
+ - 계획 파일: `.omx/plans/*.md`, `.omc/plans/*.md`, `docs/superpowers/plans/*.md`, `~/.claude/plans/*.md`, ralph `prd.json`, ultragoal `goals.json`
18
+ - 리뷰 기록(`*-critic-r2.md` 등)은 다른 계획이 없을 때만 쓴다.
19
+ - 단계: 마지막 `update_plan` 의 계획. `[>]` 가 진행 중인 단계다. `update_plan` 이 없으면 이 세션에서 사용자가 입력한 요청(최근 10개)이 단계다.
20
+ - 하위 목록: 진행 중인 단계(없으면 마지막 요청) 뒤의 최근 도구 호출 5개.
21
+
22
+ ## 실행
23
+
24
+ 스크립트는 이 스킬 폴더의 `scripts/progress.mjs` 다. Codex 가 셸에 주는 `CODEX_THREAD_ID` 로 지금 세션의 기록을 찾는다.
25
+
26
+ | 사용자 인자 | 명령 |
27
+ |---|---|
28
+ | 없음, `show` | `node "<스킬 폴더>/scripts/progress.mjs"` |
29
+ | `--depth N` | `node "<스킬 폴더>/scripts/progress.mjs" --depth N` (계획 트리를 N 단계까지 펼침, 기본 2) |
30
+ | `--pane`, `on` | `node "<스킬 폴더>/scripts/progress.mjs" --pane on` |
31
+ | `off` | `node "<스킬 폴더>/scripts/progress.mjs" --pane off` |
32
+
33
+ 1. 위 표의 명령 하나를 실행한다. 파일은 읽기만 한다.
34
+ 2. 출력은 고치지 않고 코드 블록 하나에 그대로 보인다. 그 아래에 한 줄로 지금 위치(진행 중인 단계)를 말한다.
35
+ 3. `--pane` 결과가 `tmux 에 닿지 못함` 이면 샌드박스가 tmux 연결을 막은 것이다. 그 명령만 샌드박스 밖 실행 승인을 요청한다. 승인을 요청할 수 없으면 사용자가 입력창에 `! node "<스킬 폴더>/scripts/progress.mjs" --pane on` 으로 직접 실행하도록 안내한다.
36
+ 4. `Codex 세션 기록을 찾지 못함` 이면 Codex 밖에서 실행한 것이다. 사용자에게 기록 파일 경로를 받아 `--rollout <파일>` 로 실행한다.
37
+
38
+ ## 한계
39
+
40
+ - 상시 패널이 아니다. 칸 없이 쓰면 부른 때의 상태만 보인다.
41
+ - 칸은 tmux 안에서만 열린다. 칸은 `--pane off` 나 tmux 로 닫을 때까지 남는다.
42
+ - 기록은 끝에서부터 32 MB 까지만 읽는다. 아주 긴 세션의 앞쪽 계획과 요청은 보이지 않을 수 있다.