opencodekit 0.21.10 → 0.23.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 (213) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +4 -25
  3. package/dist/template/.opencode/.template-manifest.json +115 -188
  4. package/dist/template/.opencode/AGENTS.md +127 -484
  5. package/dist/template/.opencode/README.md +2 -2
  6. package/dist/template/.opencode/agent/build.md +158 -356
  7. package/dist/template/.opencode/agent/explore.md +0 -1
  8. package/dist/template/.opencode/agent/plan.md +7 -16
  9. package/dist/template/.opencode/agent/review.md +0 -1
  10. package/dist/template/.opencode/agent/scout.md +2 -3
  11. package/dist/template/.opencode/agent/vision.md +0 -1
  12. package/dist/template/.opencode/artifacts/.active +1 -0
  13. package/dist/template/.opencode/artifacts/example/plan.md +12 -0
  14. package/dist/template/.opencode/artifacts/example/progress.md +4 -0
  15. package/dist/template/.opencode/artifacts/example/research.md +4 -0
  16. package/dist/template/.opencode/artifacts/example/spec.md +16 -0
  17. package/dist/template/.opencode/artifacts/todo.md +5 -0
  18. package/dist/template/.opencode/artifacts/verify.log +4 -0
  19. package/dist/template/.opencode/command/clarify.md +46 -0
  20. package/dist/template/.opencode/command/commit.md +53 -0
  21. package/dist/template/.opencode/command/create.md +29 -71
  22. package/dist/template/.opencode/command/design.md +1 -2
  23. package/dist/template/.opencode/command/explore.md +3 -4
  24. package/dist/template/.opencode/command/fix.md +55 -0
  25. package/dist/template/.opencode/command/improve-architecture.md +55 -0
  26. package/dist/template/.opencode/command/init.md +86 -69
  27. package/dist/template/.opencode/command/plan.md +30 -60
  28. package/dist/template/.opencode/command/pr.md +10 -28
  29. package/dist/template/.opencode/command/refactor.md +65 -0
  30. package/dist/template/.opencode/command/research.md +7 -29
  31. package/dist/template/.opencode/command/review-codebase.md +6 -13
  32. package/dist/template/.opencode/command/ship.md +136 -78
  33. package/dist/template/.opencode/command/test.md +66 -0
  34. package/dist/template/.opencode/command/ui-review.md +2 -4
  35. package/dist/template/.opencode/command/verify.md +15 -23
  36. package/dist/template/.opencode/dcp.jsonc +96 -85
  37. package/dist/template/.opencode/memory/README.md +4 -6
  38. package/dist/template/.opencode/memory/_templates/adr.md +45 -0
  39. package/dist/template/.opencode/memory/_templates/prd.md +1 -1
  40. package/dist/template/.opencode/memory/_templates/roadmap.md +1 -1
  41. package/dist/template/.opencode/memory/_templates/state.md +1 -1
  42. package/dist/template/.opencode/memory/project/gotchas.md +4 -4
  43. package/dist/template/.opencode/memory/project/project.md +2 -2
  44. package/dist/template/.opencode/memory/project/roadmap.md +1 -1
  45. package/dist/template/.opencode/memory/project/state.md +2 -2
  46. package/dist/template/.opencode/memory/project/tech-stack.md +2 -2
  47. package/dist/template/.opencode/memory/session-context.md +1 -1
  48. package/dist/template/.opencode/opencode.json +14 -152
  49. package/dist/template/.opencode/plugin/README.md +2 -2
  50. package/dist/template/.opencode/plugin/guard.ts +62 -0
  51. package/dist/template/.opencode/plugin/{lib/memory-admin-tools.ts → memory/admin.ts} +4 -4
  52. package/dist/template/.opencode/plugin/{lib → memory}/capture.ts +1 -1
  53. package/dist/template/.opencode/plugin/{lib → memory}/compile.ts +2 -2
  54. package/dist/template/.opencode/plugin/{lib → memory}/context.ts +1 -1
  55. package/dist/template/.opencode/plugin/{lib → memory}/curator.ts +1 -1
  56. package/dist/template/.opencode/plugin/{lib → memory}/db/observations.ts +102 -3
  57. package/dist/template/.opencode/plugin/{lib → memory}/db/schema.ts +43 -1
  58. package/dist/template/.opencode/plugin/{lib → memory}/db/types.ts +22 -0
  59. package/dist/template/.opencode/plugin/{lib/memory-db.ts → memory/db.ts} +1 -1
  60. package/dist/template/.opencode/plugin/{lib → memory}/distill.ts +1 -1
  61. package/dist/template/.opencode/plugin/{lib/memory-helpers.ts → memory/helpers.ts} +5 -1
  62. package/dist/template/.opencode/plugin/{lib/memory-hooks.ts → memory/hooks.ts} +1 -1
  63. package/dist/template/.opencode/plugin/{lib → memory}/index-generator.ts +2 -2
  64. package/dist/template/.opencode/plugin/{lib → memory}/inject.ts +1 -1
  65. package/dist/template/.opencode/plugin/{lib → memory}/lint.ts +2 -2
  66. package/dist/template/.opencode/plugin/memory/tools.ts +322 -0
  67. package/dist/template/.opencode/plugin/{lib → memory}/validate.ts +2 -2
  68. package/dist/template/.opencode/plugin/memory.ts +7 -17
  69. package/dist/template/.opencode/plugin/srcwalk.ts +721 -0
  70. package/dist/template/.opencode/skill/agent-code-quality-gate/SKILL.md +98 -0
  71. package/dist/template/.opencode/skill/behavioral-kernel/SKILL.md +52 -0
  72. package/dist/template/.opencode/skill/brainstorming/SKILL.md +1 -1
  73. package/dist/template/.opencode/skill/browser-testing-with-devtools/SKILL.md +85 -0
  74. package/dist/template/.opencode/skill/code-cleanup/SKILL.md +114 -0
  75. package/dist/template/.opencode/skill/code-navigation/SKILL.md +142 -0
  76. package/dist/template/.opencode/skill/code-review-and-quality/SKILL.md +131 -0
  77. package/dist/template/.opencode/skill/context-engineering/SKILL.md +1 -1
  78. package/dist/template/.opencode/skill/debugging-and-error-recovery/SKILL.md +109 -0
  79. package/dist/template/.opencode/skill/deep-module-design/SKILL.md +207 -0
  80. package/dist/template/.opencode/skill/development-lifecycle/SKILL.md +26 -45
  81. package/dist/template/.opencode/skill/gemini-large-context/SKILL.md +4 -4
  82. package/dist/template/.opencode/skill/git-workflow-and-versioning/SKILL.md +77 -0
  83. package/dist/template/.opencode/skill/grill-me/SKILL.md +140 -0
  84. package/dist/template/.opencode/skill/memory-system/SKILL.md +9 -10
  85. package/dist/template/.opencode/skill/opensrc/references/example-workflow.md +1 -1
  86. package/dist/template/.opencode/skill/planning-and-task-breakdown/SKILL.md +116 -0
  87. package/dist/template/.opencode/skill/shipping-and-launch/SKILL.md +95 -0
  88. package/dist/template/.opencode/skill/source-driven-development/SKILL.md +103 -0
  89. package/dist/template/.opencode/skill/spec-driven-development/SKILL.md +121 -0
  90. package/dist/template/.opencode/skill/srcwalk/SKILL.md +161 -0
  91. package/dist/template/.opencode/skill/subagent-driven-development/SKILL.md +1 -1
  92. package/dist/template/.opencode/skill/ubiquitous-language/SKILL.md +184 -0
  93. package/dist/template/.opencode/skill/using-git-worktrees/SKILL.md +6 -6
  94. package/dist/template/.opencode/skill/verification-before-completion/SKILL.md +6 -6
  95. package/dist/template/.opencode/skill/verification-before-completion/references/VERIFICATION_PROTOCOL.md +5 -5
  96. package/package.json +76 -76
  97. package/dist/template/.opencode/AGENT_ALIGNMENT.md +0 -564
  98. package/dist/template/.opencode/agent/painter.md +0 -83
  99. package/dist/template/.opencode/command/compound.md +0 -240
  100. package/dist/template/.opencode/command/curate.md +0 -299
  101. package/dist/template/.opencode/command/handoff.md +0 -149
  102. package/dist/template/.opencode/command/health.md +0 -356
  103. package/dist/template/.opencode/command/init-context.md +0 -297
  104. package/dist/template/.opencode/command/init-user.md +0 -125
  105. package/dist/template/.opencode/command/iterate.md +0 -200
  106. package/dist/template/.opencode/command/lfg.md +0 -173
  107. package/dist/template/.opencode/command/resume.md +0 -78
  108. package/dist/template/.opencode/command/status.md +0 -126
  109. package/dist/template/.opencode/command/ui-slop-check.md +0 -169
  110. package/dist/template/.opencode/plans/1768385996691-silent-wizard.md +0 -247
  111. package/dist/template/.opencode/plans/1770006237537-mighty-otter.md +0 -418
  112. package/dist/template/.opencode/plans/1770006913647-glowing-forest.md +0 -170
  113. package/dist/template/.opencode/plans/1770013678126-witty-planet.md +0 -278
  114. package/dist/template/.opencode/plans/1770112267595-shiny-rocket.md +0 -258
  115. package/dist/template/.opencode/plans/swarm-protocol.md +0 -123
  116. package/dist/template/.opencode/plugin/lib/memory-tools.ts +0 -535
  117. package/dist/template/.opencode/skill/agent-evals/SKILL.md +0 -208
  118. package/dist/template/.opencode/skill/anti-ai-slop/SKILL.md +0 -76
  119. package/dist/template/.opencode/skill/augment-context-engine/SKILL.md +0 -122
  120. package/dist/template/.opencode/skill/augment-context-engine/mcp.json +0 -6
  121. package/dist/template/.opencode/skill/beads/SKILL.md +0 -182
  122. package/dist/template/.opencode/skill/beads/references/BEST_PRACTICES.md +0 -27
  123. package/dist/template/.opencode/skill/beads/references/BOUNDARIES.md +0 -219
  124. package/dist/template/.opencode/skill/beads/references/DEPENDENCIES.md +0 -124
  125. package/dist/template/.opencode/skill/beads/references/EXAMPLES.md +0 -45
  126. package/dist/template/.opencode/skill/beads/references/FILE_CLAIMING.md +0 -101
  127. package/dist/template/.opencode/skill/beads/references/GIT_SYNC.md +0 -25
  128. package/dist/template/.opencode/skill/beads/references/HIERARCHY.md +0 -71
  129. package/dist/template/.opencode/skill/beads/references/MULTI_AGENT.md +0 -40
  130. package/dist/template/.opencode/skill/beads/references/RESUMABILITY.md +0 -177
  131. package/dist/template/.opencode/skill/beads/references/SESSION_PROTOCOL.md +0 -61
  132. package/dist/template/.opencode/skill/beads/references/TASK_CREATION.md +0 -38
  133. package/dist/template/.opencode/skill/beads/references/TROUBLESHOOTING.md +0 -38
  134. package/dist/template/.opencode/skill/beads/references/WORKFLOWS.md +0 -226
  135. package/dist/template/.opencode/skill/brand-asset-protocol/SKILL.md +0 -222
  136. package/dist/template/.opencode/skill/code-search-patterns/SKILL.md +0 -224
  137. package/dist/template/.opencode/skill/code-simplification/SKILL.md +0 -211
  138. package/dist/template/.opencode/skill/context-condensation/SKILL.md +0 -149
  139. package/dist/template/.opencode/skill/context-initialization/SKILL.md +0 -69
  140. package/dist/template/.opencode/skill/context-management/SKILL.md +0 -390
  141. package/dist/template/.opencode/skill/deep-research/SKILL.md +0 -384
  142. package/dist/template/.opencode/skill/design-direction-advisor/SKILL.md +0 -139
  143. package/dist/template/.opencode/skill/dispatching-parallel-agents/SKILL.md +0 -191
  144. package/dist/template/.opencode/skill/executing-plans/SKILL.md +0 -247
  145. package/dist/template/.opencode/skill/figma-go/SKILL.md +0 -65
  146. package/dist/template/.opencode/skill/finishing-a-development-branch/SKILL.md +0 -357
  147. package/dist/template/.opencode/skill/full-output-enforcement/SKILL.md +0 -62
  148. package/dist/template/.opencode/skill/gh-address-comments/SKILL.md +0 -29
  149. package/dist/template/.opencode/skill/gh-address-comments/scripts/fetch_comments.py +0 -237
  150. package/dist/template/.opencode/skill/gh-fix-ci/SKILL.md +0 -38
  151. package/dist/template/.opencode/skill/gh-fix-ci/scripts/inspect_pr_checks.py +0 -509
  152. package/dist/template/.opencode/skill/hi-fi-prototype-html/SKILL.md +0 -253
  153. package/dist/template/.opencode/skill/html-deck-export/SKILL.md +0 -189
  154. package/dist/template/.opencode/skill/index-knowledge/SKILL.md +0 -413
  155. package/dist/template/.opencode/skill/memory-grounding/SKILL.md +0 -68
  156. package/dist/template/.opencode/skill/playwriter/SKILL.md +0 -158
  157. package/dist/template/.opencode/skill/portless/SKILL.md +0 -109
  158. package/dist/template/.opencode/skill/prd/SKILL.md +0 -146
  159. package/dist/template/.opencode/skill/prd-task/SKILL.md +0 -182
  160. package/dist/template/.opencode/skill/prd-task/references/prd-schema.json +0 -124
  161. package/dist/template/.opencode/skill/prompt-leverage/SKILL.md +0 -90
  162. package/dist/template/.opencode/skill/prompt-leverage/references/framework.md +0 -91
  163. package/dist/template/.opencode/skill/prompt-leverage/scripts/augment_prompt.py +0 -157
  164. package/dist/template/.opencode/skill/receiving-code-review/SKILL.md +0 -263
  165. package/dist/template/.opencode/skill/reconcile/SKILL.md +0 -183
  166. package/dist/template/.opencode/skill/reflection-checkpoints/SKILL.md +0 -183
  167. package/dist/template/.opencode/skill/requesting-code-review/SKILL.md +0 -443
  168. package/dist/template/.opencode/skill/requesting-code-review/references/specialist-profiles.md +0 -108
  169. package/dist/template/.opencode/skill/requesting-code-review/review.md +0 -160
  170. package/dist/template/.opencode/skill/rtk-command-compression/SKILL.md +0 -134
  171. package/dist/template/.opencode/skill/screenshot/SKILL.md +0 -48
  172. package/dist/template/.opencode/skill/screenshot/scripts/ensure_macos_permissions.sh +0 -54
  173. package/dist/template/.opencode/skill/screenshot/scripts/macos_display_info.swift +0 -22
  174. package/dist/template/.opencode/skill/screenshot/scripts/macos_permissions.swift +0 -40
  175. package/dist/template/.opencode/skill/screenshot/scripts/macos_window_info.swift +0 -126
  176. package/dist/template/.opencode/skill/screenshot/scripts/take_screenshot.ps1 +0 -163
  177. package/dist/template/.opencode/skill/screenshot/scripts/take_screenshot.py +0 -585
  178. package/dist/template/.opencode/skill/security-threat-model/SKILL.md +0 -36
  179. package/dist/template/.opencode/skill/security-threat-model/references/prompt-template.md +0 -255
  180. package/dist/template/.opencode/skill/security-threat-model/references/security-controls-and-assets.md +0 -32
  181. package/dist/template/.opencode/skill/sharing-skills/SKILL.md +0 -214
  182. package/dist/template/.opencode/skill/skill-creator/SKILL.md +0 -181
  183. package/dist/template/.opencode/skill/skill-installer/SKILL.md +0 -58
  184. package/dist/template/.opencode/skill/skill-installer/scripts/github_utils.py +0 -21
  185. package/dist/template/.opencode/skill/skill-installer/scripts/install-skill-from-github.py +0 -313
  186. package/dist/template/.opencode/skill/skill-installer/scripts/list-skills.py +0 -106
  187. package/dist/template/.opencode/skill/swarm-coordination/SKILL.md +0 -244
  188. package/dist/template/.opencode/skill/swarm-coordination/references/architecture.md +0 -39
  189. package/dist/template/.opencode/skill/swarm-coordination/references/delegation-worker-protocol.md +0 -145
  190. package/dist/template/.opencode/skill/swarm-coordination/references/dependency-graph.md +0 -50
  191. package/dist/template/.opencode/skill/swarm-coordination/references/drift-check.md +0 -90
  192. package/dist/template/.opencode/skill/swarm-coordination/references/integration-beads.md +0 -20
  193. package/dist/template/.opencode/skill/swarm-coordination/references/launch-flow.md +0 -186
  194. package/dist/template/.opencode/skill/swarm-coordination/references/reconciler.md +0 -172
  195. package/dist/template/.opencode/skill/swarm-coordination/references/tier-enforcement.md +0 -78
  196. package/dist/template/.opencode/skill/swarm-coordination/references/tmux-integration.md +0 -134
  197. package/dist/template/.opencode/skill/systematic-debugging/SKILL.md +0 -402
  198. package/dist/template/.opencode/skill/terse-output-mode/SKILL.md +0 -95
  199. package/dist/template/.opencode/skill/think-in-code/SKILL.md +0 -136
  200. package/dist/template/.opencode/skill/ux-quality-gates/SKILL.md +0 -137
  201. package/dist/template/.opencode/skill/v1-run/SKILL.md +0 -175
  202. package/dist/template/.opencode/skill/v1-run/mcp.json +0 -6
  203. package/dist/template/.opencode/skill/verification-gates/SKILL.md +0 -63
  204. package/dist/template/.opencode/skill/visual-analysis/SKILL.md +0 -154
  205. package/dist/template/.opencode/skill/web-design-guidelines/SKILL.md +0 -46
  206. package/dist/template/.opencode/skill/workspace-setup/SKILL.md +0 -76
  207. package/dist/template/.opencode/skill/writing-plans/SKILL.md +0 -320
  208. /package/dist/template/.opencode/plugin/{lib → memory}/compact.ts +0 -0
  209. /package/dist/template/.opencode/plugin/{lib → memory}/db/graph.ts +0 -0
  210. /package/dist/template/.opencode/plugin/{lib → memory}/db/maintenance.ts +0 -0
  211. /package/dist/template/.opencode/plugin/{lib → memory}/db/pipeline.ts +0 -0
  212. /package/dist/template/.opencode/plugin/{lib → memory}/notify.ts +0 -0
  213. /package/dist/template/.opencode/plugin/{lib → memory}/operation-log.ts +0 -0
@@ -1,585 +0,0 @@
1
- #!/usr/bin/env python3
2
- """Cross-platform screenshot helper for Codex skills."""
3
-
4
- from __future__ import annotations
5
-
6
- import argparse
7
- import datetime as dt
8
- import json
9
- import os
10
- import platform
11
- import shutil
12
- import subprocess
13
- import tempfile
14
- from pathlib import Path
15
-
16
- SCRIPT_DIR = Path(__file__).resolve().parent
17
- MAC_PERM_SCRIPT = SCRIPT_DIR / "macos_permissions.swift"
18
- MAC_PERM_HELPER = SCRIPT_DIR / "ensure_macos_permissions.sh"
19
- MAC_WINDOW_SCRIPT = SCRIPT_DIR / "macos_window_info.swift"
20
- MAC_DISPLAY_SCRIPT = SCRIPT_DIR / "macos_display_info.swift"
21
- TEST_MODE_ENV = "CODEX_SCREENSHOT_TEST_MODE"
22
- TEST_PLATFORM_ENV = "CODEX_SCREENSHOT_TEST_PLATFORM"
23
- TEST_WINDOWS_ENV = "CODEX_SCREENSHOT_TEST_WINDOWS"
24
- TEST_DISPLAYS_ENV = "CODEX_SCREENSHOT_TEST_DISPLAYS"
25
- TEST_PNG = (
26
- b"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01"
27
- b"\x08\x06\x00\x00\x00\x1f\x15\xc4\x89\x00\x00\x00\x0cIDAT\x08\xd7c"
28
- b"\xf8\xff\xff?\x00\x05\xfe\x02\xfeA\xad\x1c\x1c\x00\x00\x00\x00IEND"
29
- b"\xaeB`\x82"
30
- )
31
-
32
-
33
- def parse_region(value: str) -> tuple[int, int, int, int]:
34
- parts = [p.strip() for p in value.split(",")]
35
- if len(parts) != 4:
36
- raise argparse.ArgumentTypeError("region must be x,y,w,h")
37
- try:
38
- x, y, w, h = (int(p) for p in parts)
39
- except ValueError as exc:
40
- raise argparse.ArgumentTypeError("region values must be integers") from exc
41
- if w <= 0 or h <= 0:
42
- raise argparse.ArgumentTypeError("region width and height must be positive")
43
- return x, y, w, h
44
-
45
-
46
- def test_mode_enabled() -> bool:
47
- value = os.environ.get(TEST_MODE_ENV, "")
48
- return value.lower() in {"1", "true", "yes", "on"}
49
-
50
-
51
- def normalize_platform(value: str) -> str:
52
- lowered = value.strip().lower()
53
- if lowered in {"darwin", "mac", "macos", "osx"}:
54
- return "Darwin"
55
- if lowered in {"linux", "ubuntu"}:
56
- return "Linux"
57
- if lowered in {"windows", "win"}:
58
- return "Windows"
59
- return value
60
-
61
-
62
- def test_platform_override() -> str | None:
63
- value = os.environ.get(TEST_PLATFORM_ENV)
64
- if value:
65
- return normalize_platform(value)
66
- return None
67
-
68
-
69
- def parse_int_list(value: str) -> list[int]:
70
- results: list[int] = []
71
- for part in value.split(","):
72
- part = part.strip()
73
- if not part:
74
- continue
75
- try:
76
- results.append(int(part))
77
- except ValueError:
78
- continue
79
- return results
80
-
81
-
82
- def test_window_ids() -> list[int]:
83
- value = os.environ.get(TEST_WINDOWS_ENV, "101,102")
84
- ids = parse_int_list(value)
85
- return ids or [101]
86
-
87
-
88
- def test_display_ids() -> list[int]:
89
- value = os.environ.get(TEST_DISPLAYS_ENV, "1,2")
90
- ids = parse_int_list(value)
91
- return ids or [1]
92
-
93
-
94
- def write_test_png(path: Path) -> None:
95
- ensure_parent(path)
96
- path.write_bytes(TEST_PNG)
97
-
98
-
99
- def timestamp() -> str:
100
- return dt.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
101
-
102
-
103
- def default_filename(fmt: str, prefix: str = "screenshot") -> str:
104
- return f"{prefix}-{timestamp()}.{fmt}"
105
-
106
-
107
- def mac_default_dir() -> Path:
108
- desktop = Path.home() / "Desktop"
109
- try:
110
- proc = subprocess.run(
111
- ["defaults", "read", "com.apple.screencapture", "location"],
112
- check=False,
113
- capture_output=True,
114
- text=True,
115
- )
116
- location = proc.stdout.strip()
117
- if location:
118
- return Path(location).expanduser()
119
- except OSError:
120
- pass
121
- return desktop
122
-
123
-
124
- def default_dir(system: str) -> Path:
125
- home = Path.home()
126
- if system == "Darwin":
127
- return mac_default_dir()
128
- if system == "Windows":
129
- pictures = home / "Pictures"
130
- screenshots = pictures / "Screenshots"
131
- if screenshots.exists():
132
- return screenshots
133
- if pictures.exists():
134
- return pictures
135
- return home
136
- pictures = home / "Pictures"
137
- screenshots = pictures / "Screenshots"
138
- if screenshots.exists():
139
- return screenshots
140
- if pictures.exists():
141
- return pictures
142
- return home
143
-
144
-
145
- def ensure_parent(path: Path) -> None:
146
- try:
147
- path.parent.mkdir(parents=True, exist_ok=True)
148
- except OSError:
149
- # Fall back to letting the capture command report a clearer error.
150
- pass
151
-
152
-
153
- def resolve_output_path(
154
- requested_path: str | None, mode: str, fmt: str, system: str
155
- ) -> Path:
156
- if requested_path:
157
- path = Path(requested_path).expanduser()
158
- if path.exists() and path.is_dir():
159
- path = path / default_filename(fmt)
160
- elif requested_path.endswith(("/", "\\")) and not path.exists():
161
- path.mkdir(parents=True, exist_ok=True)
162
- path = path / default_filename(fmt)
163
- elif path.suffix == "":
164
- path = path.with_suffix(f".{fmt}")
165
- ensure_parent(path)
166
- return path
167
-
168
- if mode == "temp":
169
- tmp_dir = Path(tempfile.gettempdir())
170
- tmp_path = tmp_dir / default_filename(fmt, prefix="codex-shot")
171
- ensure_parent(tmp_path)
172
- return tmp_path
173
-
174
- dest_dir = default_dir(system)
175
- dest_path = dest_dir / default_filename(fmt)
176
- ensure_parent(dest_path)
177
- return dest_path
178
-
179
-
180
- def multi_output_paths(base: Path, suffixes: list[str]) -> list[Path]:
181
- if len(suffixes) <= 1:
182
- return [base]
183
- paths: list[Path] = []
184
- for suffix in suffixes:
185
- candidate = base.with_name(f"{base.stem}-{suffix}{base.suffix}")
186
- ensure_parent(candidate)
187
- paths.append(candidate)
188
- return paths
189
-
190
-
191
- def run(cmd: list[str]) -> None:
192
- try:
193
- subprocess.run(cmd, check=True)
194
- except FileNotFoundError as exc:
195
- raise SystemExit(f"required command not found: {cmd[0]}") from exc
196
- except subprocess.CalledProcessError as exc:
197
- raise SystemExit(f"command failed ({exc.returncode}): {' '.join(cmd)}") from exc
198
-
199
-
200
- def swift_json(script: Path, extra_args: list[str] | None = None) -> dict:
201
- module_cache = Path(tempfile.gettempdir()) / "codex-swift-module-cache"
202
- module_cache.mkdir(parents=True, exist_ok=True)
203
- cmd = ["swift", "-module-cache-path", str(module_cache), str(script)]
204
- if extra_args:
205
- cmd.extend(extra_args)
206
- try:
207
- proc = subprocess.run(cmd, check=True, capture_output=True, text=True)
208
- except FileNotFoundError as exc:
209
- raise SystemExit("swift not found; install Xcode command line tools") from exc
210
- except subprocess.CalledProcessError as exc:
211
- stderr = (exc.stderr or "").strip()
212
- if "ModuleCache" in stderr and "Operation not permitted" in stderr:
213
- raise SystemExit(
214
- "swift needs module-cache access; rerun with escalated permissions"
215
- ) from exc
216
- msg = stderr or (exc.stdout or "").strip() or "swift helper failed"
217
- raise SystemExit(msg) from exc
218
- try:
219
- return json.loads(proc.stdout)
220
- except json.JSONDecodeError as exc:
221
- raise SystemExit(f"swift helper returned invalid JSON: {proc.stdout.strip()}") from exc
222
-
223
-
224
- def macos_screen_capture_granted(request: bool = False) -> bool:
225
- args = ["--request"] if request else []
226
- payload = swift_json(MAC_PERM_SCRIPT, args)
227
- return bool(payload.get("screenCapture"))
228
-
229
-
230
- def ensure_macos_permissions() -> None:
231
- if os.environ.get("CODEX_SANDBOX"):
232
- raise SystemExit(
233
- "screen capture checks are blocked in the sandbox; rerun with escalated permissions"
234
- )
235
- if macos_screen_capture_granted():
236
- return
237
- subprocess.run(["bash", str(MAC_PERM_HELPER)], check=False)
238
- if not macos_screen_capture_granted():
239
- raise SystemExit(
240
- "Screen Recording permission is required; enable it in System Settings and retry"
241
- )
242
-
243
-
244
- def activate_app(app: str) -> None:
245
- safe_app = app.replace('"', '\\"')
246
- script = f'tell application "{safe_app}" to activate'
247
- subprocess.run(["osascript", "-e", script], check=False, capture_output=True, text=True)
248
-
249
-
250
- def macos_window_payload(args: argparse.Namespace, frontmost: bool, include_list: bool) -> dict:
251
- flags: list[str] = []
252
- if frontmost:
253
- flags.append("--frontmost")
254
- if args.app:
255
- flags.extend(["--app", args.app])
256
- if args.window_name:
257
- flags.extend(["--window-name", args.window_name])
258
- if include_list:
259
- flags.append("--list")
260
- return swift_json(MAC_WINDOW_SCRIPT, flags)
261
-
262
-
263
- def macos_display_indexes() -> list[int]:
264
- payload = swift_json(MAC_DISPLAY_SCRIPT)
265
- displays = payload.get("displays") or []
266
- indexes: list[int] = []
267
- for item in displays:
268
- try:
269
- value = int(item)
270
- except (TypeError, ValueError):
271
- continue
272
- if value > 0:
273
- indexes.append(value)
274
- return indexes or [1]
275
-
276
-
277
- def macos_window_ids(args: argparse.Namespace, capture_all: bool) -> list[int]:
278
- payload = macos_window_payload(
279
- args,
280
- frontmost=args.active_window,
281
- include_list=capture_all,
282
- )
283
- if capture_all:
284
- windows = payload.get("windows") or []
285
- ids: list[int] = []
286
- for item in windows:
287
- win_id = item.get("id")
288
- if win_id is None:
289
- continue
290
- try:
291
- ids.append(int(win_id))
292
- except (TypeError, ValueError):
293
- continue
294
- if ids:
295
- return ids
296
- selected = payload.get("selected") or {}
297
- win_id = selected.get("id")
298
- if win_id is not None:
299
- try:
300
- return [int(win_id)]
301
- except (TypeError, ValueError):
302
- pass
303
- raise SystemExit("no matching macOS window found; try --list-windows to inspect ids")
304
-
305
-
306
- def list_macos_windows(args: argparse.Namespace) -> None:
307
- payload = macos_window_payload(args, frontmost=args.active_window, include_list=True)
308
- windows = payload.get("windows") or []
309
- if not windows:
310
- print("no matching windows found")
311
- return
312
- for item in windows:
313
- bounds = item.get("bounds") or {}
314
- name = item.get("name") or ""
315
- width = bounds.get("width", 0)
316
- height = bounds.get("height", 0)
317
- x = bounds.get("x", 0)
318
- y = bounds.get("y", 0)
319
- print(f"{item.get('id')}\t{item.get('owner')}\t{name}\t{width}x{height}+{x}+{y}")
320
-
321
-
322
- def list_test_macos_windows(args: argparse.Namespace) -> None:
323
- owner = args.app or "TestApp"
324
- name = args.window_name or ""
325
- ids = test_window_ids()
326
- if args.active_window and ids:
327
- ids = [ids[0]]
328
- for idx, win_id in enumerate(ids, start=1):
329
- window_name = name or f"Window {idx}"
330
- print(f"{win_id}\t{owner}\t{window_name}\t800x600+0+0")
331
-
332
-
333
- def resolve_macos_windows(args: argparse.Namespace) -> list[int]:
334
- if args.app:
335
- activate_app(args.app)
336
- capture_all = not args.active_window
337
- return macos_window_ids(args, capture_all=capture_all)
338
-
339
-
340
- def resolve_test_macos_windows(args: argparse.Namespace) -> list[int]:
341
- ids = test_window_ids()
342
- if args.active_window and ids:
343
- return [ids[0]]
344
- return ids
345
-
346
-
347
- def capture_macos(
348
- args: argparse.Namespace,
349
- output: Path,
350
- *,
351
- window_id: int | None = None,
352
- display: int | None = None,
353
- ) -> None:
354
- cmd = ["screencapture", "-x", f"-t{args.format}"]
355
- if args.interactive:
356
- cmd.append("-i")
357
- if display is not None:
358
- cmd.append(f"-D{display}")
359
- effective_window_id = window_id if window_id is not None else args.window_id
360
- if effective_window_id is not None:
361
- cmd.append(f"-l{effective_window_id}")
362
- elif args.region is not None:
363
- x, y, w, h = args.region
364
- cmd.append(f"-R{x},{y},{w},{h}")
365
- cmd.append(str(output))
366
- run(cmd)
367
-
368
-
369
- def capture_linux(args: argparse.Namespace, output: Path) -> None:
370
- scrot = shutil.which("scrot")
371
- gnome = shutil.which("gnome-screenshot")
372
- imagemagick = shutil.which("import")
373
- xdotool = shutil.which("xdotool")
374
-
375
- if args.region is not None:
376
- x, y, w, h = args.region
377
- if scrot:
378
- run(["scrot", "-a", f"{x},{y},{w},{h}", str(output)])
379
- return
380
- if imagemagick:
381
- geometry = f"{w}x{h}+{x}+{y}"
382
- run(["import", "-window", "root", "-crop", geometry, str(output)])
383
- return
384
- raise SystemExit("region capture requires scrot or ImageMagick (import)")
385
-
386
- if args.window_id is not None:
387
- if imagemagick:
388
- run(["import", "-window", str(args.window_id), str(output)])
389
- return
390
- raise SystemExit("window-id capture requires ImageMagick (import)")
391
-
392
- if args.active_window:
393
- if scrot:
394
- run(["scrot", "-u", str(output)])
395
- return
396
- if gnome:
397
- run(["gnome-screenshot", "-w", "-f", str(output)])
398
- return
399
- if imagemagick and xdotool:
400
- win_id = (
401
- subprocess.check_output(["xdotool", "getactivewindow"], text=True)
402
- .strip()
403
- )
404
- run(["import", "-window", win_id, str(output)])
405
- return
406
- raise SystemExit("active-window capture requires scrot, gnome-screenshot, or import+xdotool")
407
-
408
- if scrot:
409
- run(["scrot", str(output)])
410
- return
411
- if gnome:
412
- run(["gnome-screenshot", "-f", str(output)])
413
- return
414
- if imagemagick:
415
- run(["import", "-window", "root", str(output)])
416
- return
417
- raise SystemExit("no supported screenshot tool found (scrot, gnome-screenshot, or import)")
418
-
419
-
420
- def main() -> None:
421
- parser = argparse.ArgumentParser(description=__doc__)
422
- parser.add_argument(
423
- "--path",
424
- help="output file path or directory; overrides --mode",
425
- )
426
- parser.add_argument(
427
- "--mode",
428
- choices=("default", "temp"),
429
- default="default",
430
- help="default saves to the OS screenshot location; temp saves to the temp dir",
431
- )
432
- parser.add_argument(
433
- "--format",
434
- default="png",
435
- help="image format/extension (default: png)",
436
- )
437
- parser.add_argument(
438
- "--app",
439
- help="macOS only: capture all matching on-screen windows for this app name",
440
- )
441
- parser.add_argument(
442
- "--window-name",
443
- help="macOS only: substring match for a window title (optionally scoped by --app)",
444
- )
445
- parser.add_argument(
446
- "--list-windows",
447
- action="store_true",
448
- help="macOS only: list matching window ids instead of capturing",
449
- )
450
- parser.add_argument(
451
- "--region",
452
- type=parse_region,
453
- help="capture region as x,y,w,h (pixel coordinates)",
454
- )
455
- parser.add_argument(
456
- "--window-id",
457
- type=int,
458
- help="capture a specific window id when supported",
459
- )
460
- parser.add_argument(
461
- "--active-window",
462
- action="store_true",
463
- help="capture the focused/active window only when supported",
464
- )
465
- parser.add_argument(
466
- "--interactive",
467
- action="store_true",
468
- help="use interactive selection where the OS tool supports it",
469
- )
470
- args = parser.parse_args()
471
-
472
- if args.region and args.window_id is not None:
473
- raise SystemExit("choose either --region or --window-id, not both")
474
- if args.region and args.active_window:
475
- raise SystemExit("choose either --region or --active-window, not both")
476
- if args.window_id is not None and args.active_window:
477
- raise SystemExit("choose either --window-id or --active-window, not both")
478
- if args.app and args.window_id is not None:
479
- raise SystemExit("choose either --app or --window-id, not both")
480
- if args.region and args.app:
481
- raise SystemExit("choose either --region or --app, not both")
482
- if args.region and args.window_name:
483
- raise SystemExit("choose either --region or --window-name, not both")
484
- if args.interactive and args.app:
485
- raise SystemExit("choose either --interactive or --app, not both")
486
- if args.interactive and args.window_name:
487
- raise SystemExit("choose either --interactive or --window-name, not both")
488
- if args.interactive and args.window_id is not None:
489
- raise SystemExit("choose either --interactive or --window-id, not both")
490
- if args.interactive and args.active_window:
491
- raise SystemExit("choose either --interactive or --active-window, not both")
492
- if args.list_windows and (args.region or args.window_id is not None or args.interactive):
493
- raise SystemExit("--list-windows only supports --app, --window-name, and --active-window")
494
-
495
- test_mode = test_mode_enabled()
496
- system = platform.system()
497
- if test_mode:
498
- override = test_platform_override()
499
- if override:
500
- system = override
501
- window_ids: list[int] = []
502
- display_ids: list[int] = []
503
-
504
- if system != "Darwin" and (args.app or args.window_name or args.list_windows):
505
- raise SystemExit("--app/--window-name/--list-windows are supported on macOS only")
506
-
507
- if system == "Darwin":
508
- if test_mode:
509
- if args.list_windows:
510
- list_test_macos_windows(args)
511
- return
512
- if args.window_id is not None:
513
- window_ids = [args.window_id]
514
- elif args.app or args.window_name or args.active_window:
515
- window_ids = resolve_test_macos_windows(args)
516
- elif args.region is None and not args.interactive:
517
- display_ids = test_display_ids()
518
- else:
519
- ensure_macos_permissions()
520
- if args.list_windows:
521
- list_macos_windows(args)
522
- return
523
- if args.window_id is not None:
524
- window_ids = [args.window_id]
525
- elif args.app or args.window_name or args.active_window:
526
- window_ids = resolve_macos_windows(args)
527
- elif args.region is None and not args.interactive:
528
- display_ids = macos_display_indexes()
529
-
530
- output = resolve_output_path(args.path, args.mode, args.format, system)
531
-
532
- if test_mode:
533
- if system == "Darwin":
534
- if window_ids:
535
- suffixes = [f"w{wid}" for wid in window_ids]
536
- paths = multi_output_paths(output, suffixes)
537
- for path in paths:
538
- write_test_png(path)
539
- for path in paths:
540
- print(path)
541
- return
542
- if len(display_ids) > 1:
543
- suffixes = [f"d{did}" for did in display_ids]
544
- paths = multi_output_paths(output, suffixes)
545
- for path in paths:
546
- write_test_png(path)
547
- for path in paths:
548
- print(path)
549
- return
550
- write_test_png(output)
551
- print(output)
552
- return
553
-
554
- if system == "Darwin":
555
- if window_ids:
556
- suffixes = [f"w{wid}" for wid in window_ids]
557
- paths = multi_output_paths(output, suffixes)
558
- for wid, path in zip(window_ids, paths):
559
- capture_macos(args, path, window_id=wid)
560
- for path in paths:
561
- print(path)
562
- return
563
- if len(display_ids) > 1:
564
- suffixes = [f"d{did}" for did in display_ids]
565
- paths = multi_output_paths(output, suffixes)
566
- for did, path in zip(display_ids, paths):
567
- capture_macos(args, path, display=did)
568
- for path in paths:
569
- print(path)
570
- return
571
- capture_macos(args, output)
572
- elif system == "Linux":
573
- capture_linux(args, output)
574
- elif system == "Windows":
575
- raise SystemExit(
576
- "Windows support lives in scripts/take_screenshot.ps1; run it with PowerShell"
577
- )
578
- else:
579
- raise SystemExit(f"unsupported platform: {system}")
580
-
581
- print(output)
582
-
583
-
584
- if __name__ == "__main__":
585
- main()
@@ -1,36 +0,0 @@
1
- ---
2
- name: security-threat-model
3
- description: Use when the user explicitly requests threat modeling for a repo or path, with concrete abuse paths, trust boundaries, and mitigations.
4
- version: 1.0.0
5
- tags: [planning, code-quality, research]
6
- dependencies: []
7
- ---
8
-
9
- # security-threat-model
10
-
11
- Repository-grounded threat modeling for real attack paths and mitigations.
12
-
13
- ## When to Use
14
-
15
- - User explicitly asks for threat modeling
16
- - User asks for abuse-path analysis, attacker goals, or trust-boundary review
17
-
18
- ## When NOT to Use
19
-
20
- - General code review without threat-model request
21
- - Pure style/refactor requests
22
-
23
- ## Workflow
24
-
25
- 1. Scope system/runtime components from repository evidence
26
- 2. Enumerate trust boundaries, assets, and entry points
27
- 3. Define realistic attacker capabilities
28
- 4. Model concrete abuse paths and rank by impact/likelihood
29
- 5. Validate assumptions with user (1–3 targeted questions)
30
- 6. Recommend mitigations tied to concrete files/components
31
- 7. Write final report to `<repo-name>-threat-model.md`
32
-
33
- ## References
34
-
35
- - `references/prompt-template.md`
36
- - `references/security-controls-and-assets.md`