@caddis/cli 0.0.0 → 0.1.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 (153) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +150 -1
  3. package/bundles/antigravity-plugin/agents/code-reviewer.md +47 -0
  4. package/bundles/antigravity-plugin/agents/preflight.md +53 -0
  5. package/bundles/antigravity-plugin/guard_agy.py +338 -0
  6. package/bundles/antigravity-plugin/hooks.json +36 -0
  7. package/bundles/antigravity-plugin/mcp_config.json +8 -0
  8. package/bundles/antigravity-plugin/mcp_ping_server.py +55 -0
  9. package/bundles/antigravity-plugin/plugin.json +5 -0
  10. package/bundles/antigravity-plugin/session_end_agy.py +57 -0
  11. package/bundles/antigravity-plugin/skills/_registry.md +115 -0
  12. package/bundles/antigravity-plugin/skills/add-rules/SKILL.md +45 -0
  13. package/bundles/antigravity-plugin/skills/api-design/SKILL.md +249 -0
  14. package/bundles/antigravity-plugin/skills/backend-development/SKILL.md +305 -0
  15. package/bundles/antigravity-plugin/skills/best-practices/SKILL.md +500 -0
  16. package/bundles/antigravity-plugin/skills/best-practices/agents/best-practices-referencer.md +263 -0
  17. package/bundles/antigravity-plugin/skills/best-practices/agents/codebase-context-builder.md +326 -0
  18. package/bundles/antigravity-plugin/skills/best-practices/agents/task-intent-analyzer.md +245 -0
  19. package/bundles/antigravity-plugin/skills/best-practices/references/anti-patterns.md +571 -0
  20. package/bundles/antigravity-plugin/skills/best-practices/references/before-after-examples.md +1114 -0
  21. package/bundles/antigravity-plugin/skills/best-practices/references/best-practices-guide.md +513 -0
  22. package/bundles/antigravity-plugin/skills/best-practices/references/common-workflows.md +692 -0
  23. package/bundles/antigravity-plugin/skills/best-practices/references/prompt-patterns.md +547 -0
  24. package/bundles/antigravity-plugin/skills/brainstorming/SKILL.md +57 -0
  25. package/bundles/antigravity-plugin/skills/ci-cd-pipeline/SKILL.md +315 -0
  26. package/bundles/antigravity-plugin/skills/code-documentation/SKILL.md +271 -0
  27. package/bundles/antigravity-plugin/skills/code-review/SKILL.md +122 -0
  28. package/bundles/antigravity-plugin/skills/codebase-audit/SKILL.md +204 -0
  29. package/bundles/antigravity-plugin/skills/context-curator/SKILL.md +157 -0
  30. package/bundles/antigravity-plugin/skills/cross-review/SKILL.md +40 -0
  31. package/bundles/antigravity-plugin/skills/css-architecture/SKILL.md +305 -0
  32. package/bundles/antigravity-plugin/skills/css-architecture/references/RESPONSIVE-DESIGN.md +604 -0
  33. package/bundles/antigravity-plugin/skills/database-design/SKILL.md +177 -0
  34. package/bundles/antigravity-plugin/skills/db-diagram/SKILL.md +148 -0
  35. package/bundles/antigravity-plugin/skills/db-diagram/scripts/sql_to_graph.py +1212 -0
  36. package/bundles/antigravity-plugin/skills/digress/SKILL.md +61 -0
  37. package/bundles/antigravity-plugin/skills/draw-io/SKILL.md +162 -0
  38. package/bundles/antigravity-plugin/skills/draw-io/references/aws-icons.md +677 -0
  39. package/bundles/antigravity-plugin/skills/draw-io/references/layout-guidelines.md +142 -0
  40. package/bundles/antigravity-plugin/skills/draw-io/references/troubleshooting.md +118 -0
  41. package/bundles/antigravity-plugin/skills/draw-io/references/workflows.md +103 -0
  42. package/bundles/antigravity-plugin/skills/draw-io/scripts/convert-drawio-to-png.sh +25 -0
  43. package/bundles/antigravity-plugin/skills/draw-io/scripts/find_aws_icon.py +79 -0
  44. package/bundles/antigravity-plugin/skills/error-handling/SKILL.md +260 -0
  45. package/bundles/antigravity-plugin/skills/excalidraw-db/SKILL.md +38 -0
  46. package/bundles/antigravity-plugin/skills/fastapi-dev/SKILL.md +300 -0
  47. package/bundles/antigravity-plugin/skills/feature-plan/SKILL.md +198 -0
  48. package/bundles/antigravity-plugin/skills/frontend-design/SKILL.md +193 -0
  49. package/bundles/antigravity-plugin/skills/frontend-design/references/my-tech-stack.md +127 -0
  50. package/bundles/antigravity-plugin/skills/gh-cli/SKILL.md +195 -0
  51. package/bundles/antigravity-plugin/skills/git-commit/SKILL.md +285 -0
  52. package/bundles/antigravity-plugin/skills/golden-plan/SKILL.md +577 -0
  53. package/bundles/antigravity-plugin/skills/handoff/SKILL.md +100 -0
  54. package/bundles/antigravity-plugin/skills/implement/SKILL.md +114 -0
  55. package/bundles/antigravity-plugin/skills/javascript-typescript/SKILL.md +142 -0
  56. package/bundles/antigravity-plugin/skills/kb/SKILL.md +60 -0
  57. package/bundles/antigravity-plugin/skills/mermaid-db/SKILL.md +33 -0
  58. package/bundles/antigravity-plugin/skills/mermaid-diagrams/SKILL.md +236 -0
  59. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/ENHANCEMENTS.md +264 -0
  60. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/MERMAID-SUMMARY.md +137 -0
  61. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/advanced-features.md +556 -0
  62. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/architecture-diagrams.md +192 -0
  63. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/c4-diagrams.md +410 -0
  64. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/class-diagrams.md +361 -0
  65. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/erd-diagrams.md +510 -0
  66. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/flowcharts.md +450 -0
  67. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/sequence-diagrams.md +394 -0
  68. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/troubleshooting.md +335 -0
  69. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/workflows.md +418 -0
  70. package/bundles/antigravity-plugin/skills/migrate-dir/SKILL.md +68 -0
  71. package/bundles/antigravity-plugin/skills/mockup/SKILL.md +242 -0
  72. package/bundles/antigravity-plugin/skills/particle-art/SKILL.md +243 -0
  73. package/bundles/antigravity-plugin/skills/particle-art/references/canvas-utils.ts +171 -0
  74. package/bundles/antigravity-plugin/skills/particle-art/references/dot-field.template.tsx +203 -0
  75. package/bundles/antigravity-plugin/skills/particle-art/references/flow-field.template.tsx +263 -0
  76. package/bundles/antigravity-plugin/skills/particle-art/references/node-shape.template.tsx +261 -0
  77. package/bundles/antigravity-plugin/skills/particle-art/references/shape-sampler.ts +281 -0
  78. package/bundles/antigravity-plugin/skills/particle-art/references/stipple-morph.template.tsx +167 -0
  79. package/bundles/antigravity-plugin/skills/particle-art/references/stipple.template.tsx +175 -0
  80. package/bundles/antigravity-plugin/skills/particle-art/references/trail-ghost.template.tsx +266 -0
  81. package/bundles/antigravity-plugin/skills/particle-art/references/usage-examples.md +320 -0
  82. package/bundles/antigravity-plugin/skills/playwright/API_REFERENCE.md +653 -0
  83. package/bundles/antigravity-plugin/skills/playwright/SKILL.md +454 -0
  84. package/bundles/antigravity-plugin/skills/playwright/lib/helpers.js +441 -0
  85. package/bundles/antigravity-plugin/skills/playwright/package.json +26 -0
  86. package/bundles/antigravity-plugin/skills/playwright/run.js +228 -0
  87. package/bundles/antigravity-plugin/skills/prd/SKILL.md +107 -0
  88. package/bundles/antigravity-plugin/skills/preflight/SKILL.md +435 -0
  89. package/bundles/antigravity-plugin/skills/python/SKILL.md +388 -0
  90. package/bundles/antigravity-plugin/skills/react-best-practices/SKILL.md +269 -0
  91. package/bundles/antigravity-plugin/skills/react-dev/README.md +404 -0
  92. package/bundles/antigravity-plugin/skills/react-dev/SKILL.md +459 -0
  93. package/bundles/antigravity-plugin/skills/react-dev/examples/generic-components.md +579 -0
  94. package/bundles/antigravity-plugin/skills/react-dev/examples/server-components.md +579 -0
  95. package/bundles/antigravity-plugin/skills/react-dev/references/event-handlers.md +574 -0
  96. package/bundles/antigravity-plugin/skills/react-dev/references/hooks.md +456 -0
  97. package/bundles/antigravity-plugin/skills/react-dev/references/react-19-patterns.md +638 -0
  98. package/bundles/antigravity-plugin/skills/react-dev/references/react-router.md +1002 -0
  99. package/bundles/antigravity-plugin/skills/react-dev/references/tanstack-router.md +587 -0
  100. package/bundles/antigravity-plugin/skills/refactoring/SKILL.md +486 -0
  101. package/bundles/antigravity-plugin/skills/resume/SKILL.md +36 -0
  102. package/bundles/antigravity-plugin/skills/security-review/SKILL.md +196 -0
  103. package/bundles/antigravity-plugin/skills/setup-project-ai/SKILL.md +61 -0
  104. package/bundles/antigravity-plugin/skills/ship/SKILL.md +107 -0
  105. package/bundles/antigravity-plugin/skills/ship-merge/SKILL.md +103 -0
  106. package/bundles/antigravity-plugin/skills/ship-pr/SKILL.md +102 -0
  107. package/bundles/antigravity-plugin/skills/skill-creator/LICENSE.txt +202 -0
  108. package/bundles/antigravity-plugin/skills/skill-creator/SKILL.md +491 -0
  109. package/bundles/antigravity-plugin/skills/skill-creator/agents/analyzer.md +274 -0
  110. package/bundles/antigravity-plugin/skills/skill-creator/agents/comparator.md +202 -0
  111. package/bundles/antigravity-plugin/skills/skill-creator/agents/grader.md +223 -0
  112. package/bundles/antigravity-plugin/skills/skill-creator/assets/eval_review.html +146 -0
  113. package/bundles/antigravity-plugin/skills/skill-creator/eval-viewer/generate_review.py +471 -0
  114. package/bundles/antigravity-plugin/skills/skill-creator/eval-viewer/viewer.html +1325 -0
  115. package/bundles/antigravity-plugin/skills/skill-creator/references/schemas.md +430 -0
  116. package/bundles/antigravity-plugin/skills/skill-creator/scripts/__init__.py +0 -0
  117. package/bundles/antigravity-plugin/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
  118. package/bundles/antigravity-plugin/skills/skill-creator/scripts/generate_report.py +326 -0
  119. package/bundles/antigravity-plugin/skills/skill-creator/scripts/improve_description.py +247 -0
  120. package/bundles/antigravity-plugin/skills/skill-creator/scripts/package_skill.py +136 -0
  121. package/bundles/antigravity-plugin/skills/skill-creator/scripts/quick_validate.py +103 -0
  122. package/bundles/antigravity-plugin/skills/skill-creator/scripts/run_eval.py +310 -0
  123. package/bundles/antigravity-plugin/skills/skill-creator/scripts/run_loop.py +328 -0
  124. package/bundles/antigravity-plugin/skills/skill-creator/scripts/utils.py +47 -0
  125. package/bundles/antigravity-plugin/skills/sql/SKILL.md +321 -0
  126. package/bundles/antigravity-plugin/skills/tdd/SKILL.md +37 -0
  127. package/bundles/antigravity-plugin/skills/tdd-workflow/SKILL.md +188 -0
  128. package/bundles/antigravity-plugin/skills/technical-writing/SKILL.md +286 -0
  129. package/bundles/antigravity-plugin/skills/test-strategy/SKILL.md +155 -0
  130. package/bundles/antigravity-plugin/skills/ui-brief/SKILL.md +84 -0
  131. package/bundles/antigravity-plugin/skills/ui-review/SKILL.md +176 -0
  132. package/bundles/antigravity-plugin/skills/ui-review/references/framework-fixes.md +471 -0
  133. package/bundles/antigravity-plugin/skills/ui-review/references/visual-checklist.md +236 -0
  134. package/bundles/antigravity-plugin/skills/usage-review/SKILL.md +77 -0
  135. package/bundles/antigravity-plugin/skills/use-model/SKILL.md +64 -0
  136. package/bundles/antigravity-plugin/skills/using-git-worktrees/SKILL.md +217 -0
  137. package/bundles/antigravity-plugin/skills/version/SKILL.md +18 -0
  138. package/bundles/antigravity-plugin/skills/warm-editorial-ui/DESIGN_TOKENS.md +487 -0
  139. package/bundles/antigravity-plugin/skills/warm-editorial-ui/IMPLEMENTATION_GUIDE.md +177 -0
  140. package/bundles/antigravity-plugin/skills/warm-editorial-ui/SKILL.md +732 -0
  141. package/bundles/antigravity-plugin/skills/webapp-testing/LICENSE.txt +202 -0
  142. package/bundles/antigravity-plugin/skills/webapp-testing/SKILL.md +97 -0
  143. package/bundles/antigravity-plugin/skills/webapp-testing/examples/console_logging.py +35 -0
  144. package/bundles/antigravity-plugin/skills/webapp-testing/examples/element_discovery.py +40 -0
  145. package/bundles/antigravity-plugin/skills/webapp-testing/examples/static_html_automation.py +33 -0
  146. package/bundles/antigravity-plugin/skills/webapp-testing/scripts/with_server.py +106 -0
  147. package/bundles/antigravity-plugin/skills/windows-deployment/SKILL.md +880 -0
  148. package/bundles/antigravity-plugin/skills/writing-plans/SKILL.md +384 -0
  149. package/bundles/antigravity-plugin/statusline-command-agy.sh +91 -0
  150. package/bundles/antigravity-plugin/warm_start_agy.py +149 -0
  151. package/bundles/manifest.json +6 -0
  152. package/dist/cli.js +5363 -0
  153. package/package.json +61 -4
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 junaid
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1 +1,150 @@
1
- Placeholder. Install 0.1.0 or later.
1
+ # @caddis/cli
2
+
3
+ **One command to install, update and diagnose the [caddis](https://github.com/saajunaid/caddis-plugin) dev harness across every coding agent you use.**
4
+
5
+ ```bash
6
+ npx @caddis/cli init # detect your agents, confirm, install caddis into each
7
+ npx @caddis/cli doctor # what is installed where, and what to do about it
8
+ ```
9
+
10
+ If you use more than one coding agent, you have more than one place caddis can go stale.
11
+ This CLI is the single front door.
12
+
13
+ ---
14
+
15
+ ## What it does
16
+
17
+ caddis is a **meta-installer**. It detects the agents on your machine and drives **each one's own
18
+ native install mechanism** — it never reimplements them, and it never installs an agent for you.
19
+
20
+ | Agent | Detected via | How caddis is installed | v0.1 |
21
+ | --- | --- | --- | --- |
22
+ | **Claude Code** | `claude` on PATH | its plugin marketplace | ✅ |
23
+ | **agy** (Antigravity) | `agy` on PATH | the caddis bundle shipped inside this package | ✅ |
24
+ | **Codex** | `codex` on PATH / `~/.codex` | config merge | v0.2 |
25
+ | **GitHub Copilot** | `copilot` on PATH / `.github/copilot-instructions.md` | config merge | v0.2 |
26
+
27
+ Codex and Copilot are **detected and reported** in v0.1, never written to. They are file-configured,
28
+ which means supporting them properly requires merging into config you already own — that ships when
29
+ it is safe, not before.
30
+
31
+ **Absence is graceful.** Missing agents are skipped with a reason, never an error. One agent failing
32
+ never stops the others.
33
+
34
+ ---
35
+
36
+ ## Install
37
+
38
+ ```bash
39
+ npx @caddis/cli <command> # no install
40
+ npm i -g @caddis/cli # then just: caddis <command>
41
+ ```
42
+
43
+ Requires **Node >= 20.19**.
44
+
45
+ ---
46
+
47
+ ## Commands
48
+
49
+ ### `caddis doctor`
50
+
51
+ The one worth knowing. Every agent, the caddis version each actually has, whether that matches what
52
+ this CLI ships, where the version was read from, and the exact command that fixes each gap.
53
+
54
+ ```
55
+ Environment
56
+ ✓ node 22.14.0
57
+ • platform win32 x64
58
+ • @caddis/cli 0.1.0
59
+ ✓ shipped pool 1.3.39
60
+ bundle antigravity-plugin @ 1.3.39
61
+
62
+ Agents
63
+ ▲ Claude Code — caddis 1.3.38 → 1.3.39 available
64
+ C:\Users\you\AppData\Roaming\npm\claude.CMD
65
+ agent version 2.1.220
66
+ read from `claude plugin list`
67
+ → caddis update --agent claude
68
+ ▲ agy (Antigravity) — caddis 1.3.38 → 1.3.39 available
69
+ ~\.gemini\config\plugins\caddis\plugin.json
70
+ → caddis update --agent agy
71
+ • Codex — detected — not yet supported (v0.2)
72
+
73
+ Summary
74
+ 3 of 4 agents detected · 0 current · 2 stale · 0 not installed
75
+
76
+ 2 things to fix:
77
+ • Claude Code has caddis 1.3.38, this CLI ships 1.3.39
78
+ caddis update --agent claude
79
+ • agy (Antigravity) has caddis 1.3.38, this CLI ships 1.3.39
80
+ caddis update --agent agy
81
+ ```
82
+
83
+ `--strict` exits non-zero when something needs fixing (for CI). Detected-but-unsupported agents are
84
+ information, not failures, and never trip `--strict`. `--json` gives machine-readable output.
85
+
86
+ ### `caddis status`
87
+
88
+ The same facts as a glanceable table. Running bare `caddis` does this.
89
+
90
+ ```
91
+ caddis cli 0.1.0 · pool 1.3.39
92
+
93
+ AGENT DETECTED CADDIS STATE
94
+ ───────────────── ──────── ────── ────────────────
95
+ Claude Code yes 1.3.38 update available
96
+ agy (Antigravity) yes 1.3.38 update available
97
+ Codex yes — v0.2
98
+ GitHub Copilot no — —
99
+
100
+ 2 agent(s) behind — run caddis update (or caddis doctor for detail)
101
+ ```
102
+
103
+ ### `caddis update`
104
+
105
+ Brings every detected, supported agent up to the caddis version shipped in this CLI, through that
106
+ agent's native mechanism. Agents already current are skipped (`--force` re-drives them).
107
+
108
+ ### `caddis init`
109
+
110
+ The first run. Detects, shows exactly what it is about to run, asks, then installs. `--yes` skips
111
+ the prompt for CI.
112
+
113
+ ---
114
+
115
+ ## Flags
116
+
117
+ | Flag | Effect |
118
+ | --- | --- |
119
+ | `--dry-run` | print the exact vendor commands; change nothing |
120
+ | `-y, --yes` | never prompt |
121
+ | `-a, --agent <name...>` | limit to specific agents (`claude`, `agy`, `codex`, `copilot`) |
122
+ | `--json` | machine-readable output (`doctor`, `status`) |
123
+ | `--strict` | exit 1 when something needs fixing (`doctor`) |
124
+ | `--no-update-notifier` | skip the "newer @caddis/cli available" check |
125
+
126
+ Flags work before or after the subcommand: `caddis update --dry-run` and `caddis --dry-run update`
127
+ are the same.
128
+
129
+ **Always safe to preview:**
130
+
131
+ ```bash
132
+ $ caddis update --dry-run
133
+ · Claude Code — dry run — nothing executed
134
+ would run: claude plugin marketplace update caddis
135
+ would run: claude plugin update caddis@caddis
136
+ · agy (Antigravity) — dry run — nothing executed
137
+ would run: agy plugin install <shipped bundle>
138
+ ```
139
+
140
+ ---
141
+
142
+ ## Where the caddis content comes from
143
+
144
+ The caddis bundle ships **inside this npm package**, versioned in lockstep with the CLI — the caddis
145
+ you install is the caddis you get, with no extra fetch. `doctor` compares each agent's installed
146
+ version against that shipped version; that difference is what "drift" means throughout.
147
+
148
+ ## License
149
+
150
+ MIT
@@ -0,0 +1,47 @@
1
+ ---
2
+ name: code-reviewer
3
+ description: Use this agent to review a diff or set of changes for correctness, security, and convention adherence. Use proactively after a phase is green and before commit/merge. Reads the diff and relevant files in its own context and returns a verdict + prioritized issue list — it does NOT edit code.
4
+ ---
5
+
6
+ You are a principal engineer doing a focused code review. You read the change and judge it. You do
7
+ **not** modify code — you report. Keep the main thread's context clean: return conclusions, not a tour.
8
+
9
+ ## How to review
10
+ 1. Get the diff: `git diff` (unstaged) and `git diff --staged`, plus `git status`. If given specific
11
+ files/commits, scope to those (`git show <sha>`).
12
+ 2. Read the changed files and their immediate collaborators. Check against the relevant `AGENTS.md`
13
+ (root + the folder being changed; `CLAUDE.md` is just an `@AGENTS.md` shim) — convention violations are review findings.
14
+ 3. Judge on these axes, in priority order:
15
+ - **Correctness** — does it do what was intended? Logic bugs, races, off-by-one, wrong async/await.
16
+ - **Tests** — is there a test that would fail without this change? (TDD law.) Edge cases covered?
17
+ - **Security** — injection (parameterized queries?), authn/z, secret exposure, unvalidated input,
18
+ over-broad exception swallowing that hides failures.
19
+ - **Contracts** — backend response models ↔ frontend types alignment; API shape changes; **the path
20
+ a client calls actually reaches the server** (prefixes, proxies, base URLs).
21
+ - **Conventions** — per the project's `AGENTS.md` (typed boundaries, no absolute paths, no silent
22
+ failures/logging, layering, framework idioms).
23
+ - **Simplicity** — dead code, duplication, needless abstraction (YAGNI), clearer alternative.
24
+
25
+ ## Severity
26
+ - **blocking** — must fix before merge (bug, security hole, missing test for behavior change, broken
27
+ client↔server contract, violation of a stated project law).
28
+ - **should-fix** — real issue, fix now unless there's a reason.
29
+ - **nit** — style/polish; optional.
30
+
31
+ ## Return format (always end with this)
32
+ ```
33
+ review:
34
+ verdict: approved | changes-requested
35
+ blocking:
36
+ - file: <path:line> issue: <what> fix: <concrete suggestion>
37
+ should_fix:
38
+ - file: <path:line> issue: <what> fix: <suggestion>
39
+ nits:
40
+ - file: <path:line> note: <what>
41
+ good: <one line on what's done well, if anything>
42
+ ```
43
+ `verdict: approved` requires an empty `blocking` list. Be specific with `file:line`. Do not fix; report.
44
+
45
+ **Then, as the very last line of your output (nothing after it), emit the machine verdict:**
46
+ `REVIEW: CLEAN` (empty `blocking` list) or `REVIEW: BLOCKING` (one or more blocking items). Automated
47
+ runners read only this line, so it is mandatory and must exactly match one of those two forms.
@@ -0,0 +1,53 @@
1
+ ---
2
+ name: preflight
3
+ description: Use this agent to validate an implementation plan (or a phase of it) against the ACTUAL codebase before writing code. Use proactively right after a plan is drafted and before starting a phase. Checks that every technical claim in the plan — file paths, symbol names, API shapes, data fields, dependencies — matches reality. Read-only; returns a PASS/FAIL report. Does not fix anything.
4
+ ---
5
+
6
+ You are a plan-validation specialist. Your job: catch the plan's wrong assumptions **before** they
7
+ become wasted implementation. You diagnose; you do not fix and you do not write code.
8
+
9
+ ## What to validate (7 categories)
10
+ For the plan (or the named phase) check each claim against the codebase:
11
+ 1. **File paths** — every file the plan says to create/edit: does the parent dir exist? Does an
12
+ existing file already cover it (collision/duplication)?
13
+ 2. **Symbols** — referenced functions/classes/components/hooks: do they exist with that exact name and
14
+ signature? (`grep` them.) Flag renamed/missing ones.
15
+ 3. **API shapes** — endpoints, request/response models: do the cited routes and types exist and match
16
+ the fields the plan assumes? Does the path a client will call actually reach the server (prefix/proxy)?
17
+ 4. **Data fields** — JSON paths / DB columns the plan binds to: do they exist in the models/fixtures?
18
+ 5. **Dependencies** — libraries/primitives the plan needs: declared in the manifest? installed? (e.g. a
19
+ UI primitive the plan assumes exists — confirm the component/package is actually present.)
20
+ 6. **Conventions** — does the plan's approach fit the patterns in the relevant `AGENTS.md`? Flag drift.
21
+ 7. **Test strategy** — does the plan put a failing test first for each behavior change (TDD law)?
22
+ 8. **Local-coder readiness** — could a low-capability model implement each phase with no reasoning of
23
+ its own? Flag any phase that leaves a judgment call open, names a file/symbol vaguely, omits exact
24
+ data bindings, or has a non-literal exit gate. (Supports the planner→coder handoff.)
25
+
26
+ ## Method
27
+ - Read the plan. For each claim, run the cheapest check that confirms or refutes it (Glob/Grep/Read).
28
+ - Don't trust the plan's prose — verify against files. A claim you can't verify is a finding, not a pass.
29
+
30
+ ## Return format (always end with this)
31
+ ```
32
+ preflight:
33
+ verdict: PASS | FAIL
34
+ phase: <which phase/scope validated, or "whole plan">
35
+ findings:
36
+ - category: <paths|symbols|api|data|deps|conventions|tests|local-coder>
37
+ severity: blocker | warning
38
+ claim: <what the plan asserts>
39
+ reality: <what the codebase actually shows>
40
+ fix: <what the plan should say instead>
41
+ local_coder_ready: yes | no
42
+ local_coder_gaps:
43
+ - phase: <phase> — <what a weak coder would have to reason out / what's underspecified>
44
+ verified_ok:
45
+ - <short list of key claims that checked out>
46
+ ```
47
+ `PASS` requires zero `blocker` findings. `local_coder_ready: no` lists the phases that lean on implied
48
+ reasoning (a warning, not a hard blocker unless the plan targets a local coder). Be concrete: cite the
49
+ file/symbol you checked.
50
+
51
+ **Then, as the very last line of your output (nothing after it), emit the machine verdict:**
52
+ `PREFLIGHT: PASS` (zero blocker findings) or `PREFLIGHT: FAIL` (one or more blockers). Automated runners
53
+ read only this line, so it is mandatory and must exactly match one of those two forms.
@@ -0,0 +1,338 @@
1
+ #!/usr/bin/env python3
2
+ """caddis `guard` hook for agy (Antigravity) — PreToolUse event.
3
+
4
+ Ports claude-harness/hooks/guard.py to agy's contract: the risk CLASSIFIERS are copied in verbatim
5
+ (same tiers, same regexes, same escape hatch); only the I/O envelope is rewritten. Self-contained
6
+ (the agy bundle ships neither claude-harness/hooks/ nor scripts/), stdlib-only.
7
+
8
+ agy PreToolUse stdin (camelCase protojson):
9
+ {"toolCall": {"name": "run_command", "args": {"CommandLine": "rm -rf /"}}, "stepIdx": N,
10
+ "conversationId": "…", "workspacePaths": ["…"], "transcriptPath": "…", "modelName": "…"}
11
+ NOTE: cwd is the PLUGIN dir, not the workspace — the repo root comes from workspacePaths[0].
12
+
13
+ agy PreToolUse stdout (a decision object):
14
+ deny -> {"decision": "deny", "reason": "…"} (hard block)
15
+ ask/confirm -> {"decision": "force_ask", "reason": "…"} (always prompt; defeats the allow-cache)
16
+ allow -> nothing at all. Printing {"decision":"allow"} would *override* agy's own permission
17
+ prompt for that call; staying silent falls through to normal handling, which is what
18
+ the Claude Code guard does too.
19
+
20
+ *** FAIL OPEN — the load-bearing property of this file ***
21
+ agy may fail-closed on a hook error, so a bug here must degrade to "no guard" (agy's state today),
22
+ never to a bricked agent. Every stage is wrapped: on ANY exception, malformed payload, unknown shape
23
+ or encoding problem this prints NOTHING and exits 0. It never raises, never exits non-zero, and never
24
+ emits a partial/malformed decision (the JSON is built and serialized before a single byte is printed).
25
+
26
+ Write-tier gating (classify_write) is wired defensively: agy's file-edit tool name is still
27
+ LIVE-CHECK-PENDING (see .caddis/plans/agy-hooks-port.md), so it applies only to a tool whose name
28
+ looks like an edit/write and whose args carry a path. Unknown tools -> allow.
29
+ """
30
+ from __future__ import annotations
31
+
32
+ import json
33
+ import os
34
+ import re
35
+ import sys
36
+
37
+ # Functional identity, mirrored from scripts/claudster_config.py. Read order: the current dir first,
38
+ # the pre-rename dir as a one-version fallback.
39
+ _ARTIFACT_DIRS = (".caddis", ".claudster")
40
+ _ENV_PREFIX = "CADDIS"
41
+ _LEGACY_ENV_PREFIX = "CLAUDSTER"
42
+
43
+ # ── protected-path rules (write → deny) ──────────────────────────────────────
44
+ _SECRET_BASENAMES = {"id_rsa", "id_dsa", "id_ecdsa", "id_ed25519", "credentials",
45
+ ".npmrc", ".pypirc", ".netrc", ".pgpass", ".htpasswd"}
46
+ _SECRET_SUFFIXES = (".pem", ".key", ".p12", ".pfx", ".keystore", ".jks")
47
+ _ENV_RE = re.compile(r"(^|/)\.env(\.|$)", re.I)
48
+ _ENV_EXAMPLE_RE = re.compile(r"\.env\.(example|sample|template|dist)$", re.I)
49
+
50
+ # Lockfiles are normally regenerated by the package manager, so a hand-edit is unusual enough to
51
+ # confirm. Routine manifests (package.json/tsconfig) are deliberately NOT gated — too frequent, not risky.
52
+ _ASK_BASENAMES = {"package-lock.json", "yarn.lock", "pnpm-lock.yaml", "poetry.lock", "cargo.lock",
53
+ "uv.lock", "composer.lock", "gemfile.lock"}
54
+ _CI_WORKFLOW_RE = re.compile(r"(^|/)(\.github|\.gitea)/workflows/", re.I)
55
+
56
+
57
+ def classify_write(file_path: str) -> tuple[str, str]:
58
+ """Risk tier (deny|ask|allow) + reason for writing/editing ``file_path``."""
59
+ p = file_path.replace("\\", "/")
60
+ parts = [seg.lower() for seg in p.split("/") if seg]
61
+ base = parts[-1] if parts else ""
62
+
63
+ if any(seg in ("secrets", ".secrets") for seg in parts):
64
+ return "deny", f"writes into a secrets directory ({base})"
65
+ if ".git" in parts[:-1]:
66
+ return "deny", "writes into the .git internal directory"
67
+ if _ENV_RE.search(p) and not _ENV_EXAMPLE_RE.search(p):
68
+ return "deny", f"writes an environment/secret file ({base})"
69
+ if base in _SECRET_BASENAMES or any(base.endswith(s) for s in _SECRET_SUFFIXES):
70
+ return "deny", f"writes a credential/key file ({base})"
71
+
72
+ if base in _ASK_BASENAMES:
73
+ return "ask", f"edits a lockfile ({base})"
74
+ if _CI_WORKFLOW_RE.search(p):
75
+ return "ask", "edits a CI/CD workflow"
76
+ return "allow", ""
77
+
78
+
79
+ # ── bash rules ───────────────────────────────────────────────────────────────
80
+ # Catastrophic delete targets: a filesystem/home root or a *bare* drive root (C:\ ), NOT a drive
81
+ # subpath (E:\proj\dist falls through to ask).
82
+ _CATASTROPHIC_TARGET = re.compile(
83
+ r"--no-preserve-root"
84
+ r"|(?:^|\s)(?:/|/\*|~/|~|\$\{?HOME\}?)(?:\s|$|;|&|\|)"
85
+ r"|(?:^|\s)[A-Za-z]:[\\/]?(?:\s|$|;|&|\|)",
86
+ re.I,
87
+ )
88
+ _FORK_BOMB = re.compile(r":\(\)\s*\{\s*:\s*\|\s*:\s*&\s*\}\s*;\s*:")
89
+
90
+
91
+ def _strip_quotes(s: str) -> str:
92
+ """Drop quotes so quoted flags/targets still match (rm '-rf' \"/\" → rm -rf /)."""
93
+ return s.replace('"', "").replace("'", "")
94
+
95
+
96
+ def _has_flag(cmd: str, letter: str, longname: str) -> bool:
97
+ """True if `cmd` carries the short flag (e.g. -rf / -r) or the long flag (--recursive)."""
98
+ return bool(re.search(rf"(?:^|\s)-\w*{letter}\w*\b", cmd, re.I)) or longname in cmd.lower()
99
+
100
+
101
+ def _is_rm_recursive_force(cmd: str) -> bool:
102
+ if not re.search(r"\brm\b", cmd):
103
+ return False
104
+ return _has_flag(cmd, "r", "--recursive") and _has_flag(cmd, "f", "--force")
105
+
106
+
107
+ def _is_win_recursive_delete(cmd: str) -> bool:
108
+ """Native Windows recursive delete — the POSIX ``rm`` path is handled by _is_rm_recursive_force.
109
+
110
+ Catches PowerShell ``Remove-Item -Recurse -Force`` (and the Remove-Item aliases ri/rmdir/rd/del/
111
+ erase) plus cmd.exe ``rmdir``/``rd``/``del``/``erase`` with the ``/s`` recurse-subdirectories switch.
112
+ This is a Windows-primary environment, so these are the real footguns the POSIX rules miss."""
113
+ if not re.search(r"(?:^|[\s;&|(])(?:remove-item|ri|rmdir|rd|del|erase)\b", cmd, re.I):
114
+ return False
115
+ ps_recurse_force = bool(re.search(r"(?:^|\s)-rec\w*", cmd, re.I)) and bool(re.search(r"(?:^|\s)-for\w*", cmd, re.I))
116
+ cmd_slash_s = bool(re.search(r"(?:^|\s)/s\b", cmd, re.I))
117
+ return ps_recurse_force or cmd_slash_s
118
+
119
+
120
+ def classify_bash(command: str) -> tuple[str, str]:
121
+ """Risk tier (deny|ask|allow) + reason for a shell command."""
122
+ c = command.strip()
123
+ cl = c.lower()
124
+ n = _strip_quotes(c) # quote-normalized: defeats `rm '-rf' "/"` evasion
125
+ nl = n.lower()
126
+ rm_rf = _is_rm_recursive_force(n)
127
+ catastrophic = bool(_CATASTROPHIC_TARGET.search(n))
128
+ find_delete = bool(re.search(r"\bfind\b.*?(?:-delete\b|-exec\s+rm\b)", nl))
129
+ win_del = _is_win_recursive_delete(n)
130
+
131
+ # ── deny: catastrophic ──
132
+ if rm_rf and catastrophic:
133
+ return "deny", "recursive force-delete of a root/home path (rm -rf)"
134
+ if find_delete and catastrophic:
135
+ return "deny", "find -delete from a root/home path"
136
+ if win_del and catastrophic:
137
+ return "deny", "recursive force-delete of a root/home path (Windows Remove-Item/rmdir)"
138
+ if re.search(r"\brmtree\s*\(\s*['\"]?(?:/|~|[A-Za-z]:\\?)['\"]?\s*\)", c, re.I):
139
+ return "deny", "recursive tree delete of a root/home path (rmtree)"
140
+ if _FORK_BOMB.search(c):
141
+ return "deny", "fork bomb"
142
+ if re.search(r"\bdd\b.*\bof=/dev/", nl) or re.search(r"\bmkfs", nl) or re.search(r">\s*/dev/sd[a-z]", nl):
143
+ return "deny", "writes directly to a disk device"
144
+ if (re.search(r"\bchmod\b", nl) and _has_flag(n, "r", "--recursive")
145
+ and re.search(r"\b0?777\b", nl) and catastrophic):
146
+ return "deny", "recursive chmod 777 on a root path"
147
+
148
+ # ── ask: destructive-but-legit ──
149
+ if rm_rf:
150
+ return "ask", "recursive force-delete (rm -rf)"
151
+ if find_delete:
152
+ return "ask", "find with -delete / -exec rm"
153
+ if win_del:
154
+ return "ask", "recursive delete (Windows Remove-Item -Recurse / rmdir /s)"
155
+ # git rules tolerate intervening options (e.g. `git -c k=v push --force`) but stay within one
156
+ # command segment (the [^;&|]* won't cross a ; && || into an unrelated command). The trailing
157
+ # `+\S` catches a force-push via refspec (`git push origin +main`), not just the --force flags.
158
+ if re.search(r"\bgit\b[^;&|]*\bpush\b[^;&|]*(--force\b|--force-with-lease\b|(?:^|\s)-f\b|(?:^|\s)\+\S)", c):
159
+ return "ask", "git force-push"
160
+ if re.search(r"\bgit\b[^;&|]*\breset\s+--hard\b", c):
161
+ return "ask", "git reset --hard"
162
+ if re.search(r"\bgit\b[^;&|]*\bclean\b[^;&|]*(?:^|\s)-\w*f", c):
163
+ return "ask", "git clean (force)"
164
+ if re.search(r"\bgit\b[^;&|]*\bfilter-(repo|branch)\b", c):
165
+ return "ask", "git history rewrite"
166
+ if re.search(r"\b(drop\s+(table|database|schema)|truncate\s+table)\b", cl):
167
+ return "ask", "destructive SQL (drop/truncate)"
168
+ if re.search(r"\b(npm|yarn|pnpm)\s+publish\b|\btwine\s+upload\b|\bcargo\s+publish\b", cl):
169
+ return "ask", "publishing a package"
170
+ if re.search(r"\b(curl|wget|iwr|invoke-webrequest)\b[^|]*\|\s*(sudo\s+)?(sh|bash|zsh|iex|python)\b", cl):
171
+ return "ask", "piping a download into a shell"
172
+ return "allow", ""
173
+
174
+
175
+ # ── agy tool-shape mapping ───────────────────────────────────────────────────
176
+ # The shell tool: step type CORTEX_STEP_TYPE_RUN_COMMAND -> "run_command". The command lives at
177
+ # args.CommandLine. Extra spellings are accepted so a step-type rename can't silently un-guard the
178
+ # shell (a missed tool name = no guard at all, which is the failure we most want to avoid).
179
+ _COMMAND_TOOLS = {"run_command", "runcommand", "run_terminal_command", "bash", "shell", "terminal"}
180
+ _COMMAND_ARG_KEYS = ("CommandLine", "commandLine", "command_line", "command", "Command")
181
+
182
+ # Write-ish tool detection is heuristic until the live check pins agy's file-edit tool name.
183
+ _WRITE_NAME_RE = re.compile(r"(edit|write|create|replace|patch|append)", re.I)
184
+ _READONLY_NAME_RE = re.compile(r"(view|read|list|search|grep|find|browser|open)", re.I)
185
+ _PATH_ARG_KEYS = ("FilePath", "filePath", "file_path", "AbsolutePath", "absolutePath",
186
+ "TargetFile", "targetFile", "Path", "path")
187
+
188
+
189
+ def _first_str(args: dict, keys) -> str:
190
+ for k in keys:
191
+ v = args.get(k)
192
+ if isinstance(v, str) and v.strip():
193
+ return v
194
+ return ""
195
+
196
+
197
+ def decide(tool_name: str, args, allow_patterns: list[str]) -> tuple[str, str]:
198
+ """Top-level decision. Classify FIRST; the allow escape hatch may only DOWNGRADE an `ask` to
199
+ `allow` (never override a `deny`), and it matches the command/path value — not the JSON envelope —
200
+ so a key name like "command" can't disable the guard. Never raises on a malformed payload."""
201
+ if not isinstance(args, dict):
202
+ return "allow", ""
203
+ name = (tool_name or "").strip().lower()
204
+
205
+ if name in _COMMAND_TOOLS:
206
+ target = _first_str(args, _COMMAND_ARG_KEYS)
207
+ tier, reason = classify_bash(target) if target else ("allow", "")
208
+ elif _WRITE_NAME_RE.search(name) and not _READONLY_NAME_RE.search(name):
209
+ target = _first_str(args, _PATH_ARG_KEYS)
210
+ tier, reason = classify_write(target) if target else ("allow", "")
211
+ else:
212
+ return "allow", ""
213
+
214
+ if tier == "ask" and any(pat and pat.lower() in target.lower() for pat in allow_patterns):
215
+ return "allow", ""
216
+ return tier, reason
217
+
218
+
219
+ # ── config (per-repo escape hatch + kill switch) ─────────────────────────────
220
+ _TRUTHY = {"1", "true", "yes", "on"}
221
+
222
+
223
+ def _config_path(root: str) -> str | None:
224
+ """The repo's ``config.toml`` — ``.caddis`` preferred, legacy ``.claudster`` as fallback."""
225
+ for name in _ARTIFACT_DIRS:
226
+ cfg = os.path.join(str(root), name, "config.toml")
227
+ if os.path.isfile(cfg):
228
+ return cfg
229
+ return None
230
+
231
+
232
+ def _load_guard_config(root: str) -> dict:
233
+ """Parse the ``[guard]`` table from the repo's ``config.toml``; {} on any problem."""
234
+ cfg = _config_path(root)
235
+ if cfg is None:
236
+ return {}
237
+ try:
238
+ import tomllib
239
+ with open(cfg, "rb") as fh:
240
+ data = tomllib.load(fh)
241
+ section = data.get("guard", {})
242
+ return section if isinstance(section, dict) else {}
243
+ except Exception:
244
+ return {}
245
+
246
+
247
+ def _load_allow(root: str) -> list[str]:
248
+ allow = _load_guard_config(root).get("allow", [])
249
+ return [str(x) for x in allow] if isinstance(allow, list) else []
250
+
251
+
252
+ def guard_disabled(root: str) -> bool:
253
+ """True when the guard is turned off entirely (all tiers bypassed).
254
+
255
+ Precedence: the env var wins (global); otherwise the per-repo `[guard]` table — `enabled = false`
256
+ or `mode = "off"`. Any parse problem → not disabled (fail safe). CADDIS_GUARD_DISABLED is the
257
+ current name; the pre-rename CLAUDSTER_GUARD_DISABLED is read only when the new name is unset."""
258
+ _disabled = os.environ.get(f"{_ENV_PREFIX}_GUARD_DISABLED")
259
+ if _disabled is None:
260
+ _disabled = os.environ.get(f"{_LEGACY_ENV_PREFIX}_GUARD_DISABLED", "")
261
+ if _disabled.strip().lower() in _TRUTHY:
262
+ return True
263
+ section = _load_guard_config(root)
264
+ if section.get("enabled") is False:
265
+ return True
266
+ if str(section.get("mode", "")).strip().lower() == "off":
267
+ return True
268
+ return False
269
+
270
+
271
+ def deny_only(root: str) -> bool:
272
+ """True when the guard keeps DENY (silent hard-block) but suppresses the ASK tier (ask -> allow =
273
+ silence), so it NEVER prompts — for autonomous / no-prompt workflows that still want a catastrophe
274
+ net. Env `CADDIS_GUARD_MODE=deny-only` (`CLAUDSTER_GUARD_MODE` fallback); config `[guard] mode =
275
+ "deny-only"`. Read silently."""
276
+ _mode = os.environ.get(f"{_ENV_PREFIX}_GUARD_MODE")
277
+ if _mode is None:
278
+ _mode = os.environ.get(f"{_LEGACY_ENV_PREFIX}_GUARD_MODE", "")
279
+ if _mode.strip().lower() == "deny-only":
280
+ return True
281
+ section = _load_guard_config(root)
282
+ return str(section.get("mode", "")).strip().lower() == "deny-only"
283
+
284
+
285
+ # ── hook I/O glue (agy envelope) ─────────────────────────────────────────────
286
+ _AGY_DECISION = {"deny": "deny", "ask": "force_ask"}
287
+
288
+
289
+ def _emit(tier: str, reason: str) -> None:
290
+ """Serialize the decision FIRST, then print once — a failure mid-build can never leave agy
291
+ reading half an object. Silence (allow) is the default for anything that isn't deny/ask."""
292
+ decision = _AGY_DECISION.get(tier)
293
+ if not decision:
294
+ return
295
+ tail = (" Blocked as too dangerous to run automatically — do it by hand if you are certain."
296
+ if tier == "deny" else " Confirm only if this is intended.")
297
+ payload = json.dumps({"decision": decision, "reason": f"[caddis guard] {reason}.{tail}"})
298
+ sys.stdout.write(payload)
299
+
300
+
301
+ def main() -> None:
302
+ tier, reason = "allow", ""
303
+ try:
304
+ _reconfig = getattr(sys.stdout, "reconfigure", None)
305
+ if _reconfig:
306
+ try:
307
+ _reconfig(encoding="utf-8")
308
+ except Exception:
309
+ pass
310
+ try:
311
+ data = json.load(sys.stdin)
312
+ except Exception:
313
+ return # malformed payload → fail open, silently
314
+ if not isinstance(data, dict):
315
+ return
316
+ call = data.get("toolCall")
317
+ if not isinstance(call, dict):
318
+ return
319
+ workspaces = data.get("workspacePaths") or []
320
+ root = workspaces[0] if isinstance(workspaces, list) and workspaces else os.getcwd()
321
+ if guard_disabled(str(root)):
322
+ return # kill switch: bypass every tier
323
+ tier, reason = decide(str(call.get("name") or ""), call.get("args"), _load_allow(str(root)))
324
+ if tier == "ask" and deny_only(str(root)):
325
+ tier = "allow" # deny-only: keep catastrophe blocks, never force_ask (no plan interruption)
326
+ except Exception:
327
+ return # ANY unexpected shape/error → no guard, never a crash and never a bad decision
328
+ finally:
329
+ try:
330
+ _emit(tier, reason)
331
+ except Exception:
332
+ pass
333
+ # Always exit 0: a non-zero code from a PreToolUse hook is an agy hook *error*.
334
+ sys.exit(0)
335
+
336
+
337
+ if __name__ == "__main__":
338
+ main()
@@ -0,0 +1,36 @@
1
+ {
2
+ "hooks": {
3
+ "PreToolUse": [
4
+ {
5
+ "matcher": "*",
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "python guard_agy.py",
10
+ "windows": "python guard_agy.py",
11
+ "linux": "python3 guard_agy.py",
12
+ "osx": "python3 guard_agy.py"
13
+ }
14
+ ]
15
+ }
16
+ ],
17
+ "PreInvocation": [
18
+ {
19
+ "type": "command",
20
+ "command": "python warm_start_agy.py",
21
+ "windows": "python warm_start_agy.py",
22
+ "linux": "python3 warm_start_agy.py",
23
+ "osx": "python3 warm_start_agy.py"
24
+ }
25
+ ],
26
+ "Stop": [
27
+ {
28
+ "type": "command",
29
+ "command": "python session_end_agy.py",
30
+ "windows": "python session_end_agy.py",
31
+ "linux": "python3 session_end_agy.py",
32
+ "osx": "python3 session_end_agy.py"
33
+ }
34
+ ]
35
+ }
36
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "mcpServers": {
3
+ "caddis": {
4
+ "command": "python",
5
+ "args": ["mcp_ping_server.py"]
6
+ }
7
+ }
8
+ }