shimwrappercheck 0.2.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 (48) hide show
  1. package/AGENTS.md +21 -0
  2. package/README.md +286 -0
  3. package/bin/git +5 -0
  4. package/bin/shim +5 -0
  5. package/bin/shimwrappercheck +2 -0
  6. package/bin/supabase +5 -0
  7. package/dashboard/.next/cache/config.json +7 -0
  8. package/dashboard/.next/package.json +1 -0
  9. package/dashboard/.next/routes-manifest.json +1 -0
  10. package/dashboard/.next/trace +1 -0
  11. package/dashboard/README.md +32 -0
  12. package/dashboard/app/agents/page.tsx +88 -0
  13. package/dashboard/app/api/agents-md/route.ts +68 -0
  14. package/dashboard/app/api/config/route.ts +51 -0
  15. package/dashboard/app/api/run-checks/route.ts +54 -0
  16. package/dashboard/app/api/settings/route.ts +126 -0
  17. package/dashboard/app/api/status/route.ts +38 -0
  18. package/dashboard/app/config/page.tsx +77 -0
  19. package/dashboard/app/globals.css +20 -0
  20. package/dashboard/app/layout.tsx +23 -0
  21. package/dashboard/app/page.tsx +122 -0
  22. package/dashboard/app/settings/page.tsx +422 -0
  23. package/dashboard/components/Nav.tsx +33 -0
  24. package/dashboard/components/StatusCard.tsx +27 -0
  25. package/dashboard/lib/presets.ts +97 -0
  26. package/dashboard/lib/projectRoot.ts +25 -0
  27. package/dashboard/next.config.js +6 -0
  28. package/dashboard/package-lock.json +5307 -0
  29. package/dashboard/package.json +28 -0
  30. package/dashboard/postcss.config.js +6 -0
  31. package/dashboard/tailwind.config.js +14 -0
  32. package/dashboard/tsconfig.json +20 -0
  33. package/docs/SHIM_WRAPPER_CONCEPT.md +79 -0
  34. package/docs/WORKFLOW_AND_GAP_ANALYSIS.md +159 -0
  35. package/package.json +24 -0
  36. package/scripts/cli-checked.sh +307 -0
  37. package/scripts/cli.js +23 -0
  38. package/scripts/fetch-edge-logs.sh +96 -0
  39. package/scripts/git-checked.sh +194 -0
  40. package/scripts/init.js +341 -0
  41. package/scripts/install.js +303 -0
  42. package/scripts/ping-edge-health.sh +113 -0
  43. package/scripts/setup.js +55 -0
  44. package/scripts/supabase-checked.sh +330 -0
  45. package/templates/ai-code-review.sh +217 -0
  46. package/templates/git-pre-push +41 -0
  47. package/templates/husky-pre-push +46 -0
  48. package/templates/run-checks.sh +67 -0
package/AGENTS.md ADDED
@@ -0,0 +1,21 @@
1
+ # Agent instructions (shimwrappercheck)
2
+
3
+ This file is used by AI agents (Cursor, Codex, etc.) when working with this repo.
4
+ It can be edited via the dashboard (Config → AGENTS.md) so agents and humans share one source of truth.
5
+
6
+ ## Shim usage
7
+
8
+ - Use `npx supabase ...` or `npm run supabase:checked -- ...` so checks run before deploy.
9
+ - Use `npx git push` or `npm run git:checked -- push` so checks run before push.
10
+ - Run `npx shimwrappercheck init` for setup; `npx shimwrappercheck install` for PATH shims.
11
+
12
+ ## Dashboard
13
+
14
+ - The project includes a **dashboard** (Next.js app in `dashboard/`). Start with `cd dashboard && npm install && npm run dev`.
15
+ - In the dashboard you can: view status, run checks, edit `.shimwrappercheckrc`, and **edit this AGENTS.md**.
16
+ - Agents should respect AGENTS.md; editing it via the dashboard keeps agent instructions in sync.
17
+
18
+ ## Project rules
19
+
20
+ - Keep checks fast; run lint/type/build in `scripts/run-checks.sh`.
21
+ - When changing shim behavior, update README and docs/SHIM_WRAPPER_CONCEPT.md if needed.
package/README.md ADDED
@@ -0,0 +1,286 @@
1
+ # shimwrappercheck
2
+
3
+ CLI shim wrapper that enforces project checks before running a real CLI command.
4
+
5
+ Out of the box, this package ships **Supabase**, **Git**, and a **generic shim** (`supabase`, `git`, `shim` bins), but the pattern is generic:
6
+ you can reuse the scripts for other CLIs by copying/adapting them in your repo.
7
+
8
+ This package provides a `supabase` bin that you can use via `npx supabase ...` or `npm run supabase:checked -- ...`.
9
+ It is repo-agnostic: you plug in your own `scripts/run-checks.sh` and optional hooks.
10
+
11
+ ## Features
12
+
13
+ - Wraps a CLI command and enforces checks before deploy/push (Supabase + Git wrappers included, generic shim for anything else)
14
+ - Diff-aware checks (frontend/backend) based on staged/unstaged changes
15
+ - Command filtering (only run checks/hooks for specific Supabase commands)
16
+ - Network retry for flaky Supabase CLI calls
17
+ - Post-deploy hooks: health ping + logs
18
+ - Auto git push when ahead of upstream (optional)
19
+ - AI review integration (Codex default, Cursor fallback)
20
+ - Interactive setup wizard that scans your repo and configures everything
21
+ - Global installer that drops PATH shims (`supabase`, `git`, `shim`)
22
+ - Generic shim supports pre/post hooks
23
+ - **Dashboard**: Web UI to view status, run checks, **Presets & check toggles** (Einstellungen), edit `.shimwrappercheckrc`, and **edit AGENTS.md**
24
+ - **Presets**: default "Vibe Code" (GitHub + Supabase, all commands); custom presets with provider toggles; check toggles (frontend, backend, AI review)
25
+
26
+ ## Setup (one command)
27
+
28
+ Run the full setup in one go (installs package if needed, then runs the wizard):
29
+
30
+ ```bash
31
+ npx shimwrappercheck setup
32
+ ```
33
+
34
+ This installs `shimwrappercheck` as a devDependency if missing, then runs the init wizard (Supabase/Git shims, which commands, AI review, hooks, run-checks.sh, etc.). At the end you get a link to start the dashboard to change settings later.
35
+
36
+ ## Dashboard (Web UI)
37
+
38
+ A Next.js dashboard lets you manage presets, checks, config, and AGENTS.md:
39
+
40
+ ```bash
41
+ cd node_modules/shimwrappercheck/dashboard && npm install && npm run dev
42
+ ```
43
+
44
+ Then open http://localhost:3000. You can:
45
+
46
+ - **Einstellungen**: Presets (Vibe Code default, custom presets), Supabase/Git command toggles (which commands run checks/hooks), check toggles (frontend, backend, AI review)
47
+ - View status (config, presets file, AGENTS.md, run-checks script, hooks)
48
+ - Run checks only (button)
49
+ - Edit `.shimwrappercheckrc` (Config, raw)
50
+ - Edit **AGENTS.md** (agent instructions for Cursor/Codex; changes apply immediately)
51
+
52
+ **AGENTS.md** is used by AI agents; editing it in the dashboard keeps agent instructions in sync. Set `SHIM_PROJECT_ROOT` when deploying the dashboard (e.g. on Vercel) to the repo root path where `.shimwrappercheckrc` and `AGENTS.md` live.
53
+
54
+ ## Install
55
+
56
+ ```bash
57
+ npm i -D shimwrappercheck
58
+ ```
59
+
60
+ ## Global install (PATH shims)
61
+
62
+ This installs small shims into a bin directory (default: `~/.local/bin`) so you can run
63
+ `supabase`, `git`, or `shim` directly without `npx`.
64
+
65
+ ```bash
66
+ npx shimwrappercheck install
67
+ # options
68
+ # --bin-dir <path> (default: ~/.local/bin)
69
+ # --interactive (default when no flags)
70
+ # --no-interactive
71
+ # --add-path (auto-append PATH in shell config)
72
+ # --overwrite
73
+ # --dry-run
74
+ # --no-supabase | --no-git | --no-shim
75
+ # --only supabase,git,shim
76
+ ```
77
+
78
+ If the bin dir is not in PATH, add (or use `--add-path` to append automatically):
79
+
80
+ ```bash
81
+ export PATH="$HOME/.local/bin:$PATH"
82
+ ```
83
+
84
+ When multiple shell configs exist (e.g. `.zshrc` + `.zprofile`), the installer asks which file to update.
85
+
86
+ ## Quick start
87
+
88
+ 1) Add a checks script in your repo (example template below).
89
+ 2) Use the shim instead of the raw CLI.
90
+
91
+ ```bash
92
+ # Copy templates (customize to your repo)
93
+ cp node_modules/shimwrappercheck/templates/run-checks.sh scripts/run-checks.sh
94
+ cp node_modules/shimwrappercheck/templates/ai-code-review.sh scripts/ai-code-review.sh
95
+ cp node_modules/shimwrappercheck/templates/husky-pre-push .husky/pre-push
96
+
97
+ # Make scripts executable
98
+ chmod +x scripts/run-checks.sh scripts/ai-code-review.sh .husky/pre-push
99
+ ```
100
+
101
+ Add a package.json script (optional):
102
+
103
+ ```json
104
+ {
105
+ "scripts": {
106
+ "supabase:checked": "supabase"
107
+ }
108
+ }
109
+ ```
110
+
111
+ Then run:
112
+
113
+ ```bash
114
+ npm run supabase:checked -- functions deploy <function-name>
115
+ # or
116
+ npx supabase functions deploy <function-name>
117
+ ```
118
+
119
+ ## Setup wizard (init)
120
+
121
+ Run the interactive init to scan your codebase and configure the shim (or use `npx shimwrappercheck setup` to install + init in one step):
122
+
123
+ ```bash
124
+ npx shimwrappercheck init
125
+ # or
126
+ npm exec shimwrappercheck init
127
+ ```
128
+
129
+ The wizard can (defaults are tuned based on repo type):
130
+
131
+ - detect Supabase and Git usage
132
+ - ask which commands should trigger checks/hooks
133
+ - install pre-push hooks
134
+ - enable AI review and guide you through login
135
+ - create a `.shimwrappercheckrc` config
136
+
137
+ ## How it works
138
+
139
+ - The shim determines which checks to run based on git changes (e.g. `src/` vs `supabase/functions/`).
140
+ - The shim runs your checks script first (default: `scripts/run-checks.sh`).
141
+ - If checks pass, it calls the real Supabase CLI.
142
+ - Optional hooks run after deploy to ping health and fetch logs.
143
+ - Optional git auto-push can be enabled (this is **not** a git wrapper; it runs after the CLI succeeds).
144
+ - Git push checks are enforced via pre-push hooks (template provided).
145
+
146
+ ## Usage
147
+
148
+ ```bash
149
+ npx supabase functions deploy <function-name>
150
+ npm run supabase:checked -- db push
151
+
152
+ # git wrapper
153
+ npx git push
154
+ npm run git:checked -- push
155
+
156
+ # generic shim (any CLI)
157
+ npm exec --package shimwrappercheck -- shim docker build .
158
+ npm exec --package shimwrappercheck -- shim --cli terraform -- plan
159
+ ```
160
+
161
+ Generic shim hooks:
162
+
163
+ ```bash
164
+ export SHIM_CLI_PRE_HOOKS="scripts/cli-pre-hook.sh"
165
+ export SHIM_CLI_POST_HOOKS="scripts/cli-post-hook.sh"
166
+ shim docker build .
167
+ ```
168
+
169
+ Tip: Use `--` to separate shim flags from CLI args when needed:
170
+
171
+ ```bash
172
+ npm exec --package shimwrappercheck -- shim --cli docker -- build .
173
+ ```
174
+
175
+ You can also run only checks:
176
+
177
+ ```bash
178
+ npx supabase --checks-only functions deploy server
179
+ ```
180
+
181
+ ## Wrapper-only flags
182
+
183
+ These flags are consumed by the shim and are not passed to the wrapped CLI:
184
+
185
+ - `--no-checks` Skip checks for this invocation.
186
+ - `--checks-only` Run checks and exit without running Supabase.
187
+ - `--no-hooks` Skip post-deploy hooks (health/logs).
188
+ - `--no-push` Skip auto git push.
189
+ - `--no-ai-review` Passed through to the checks script (template supports it).
190
+ - `--with-frontend` Force frontend checks even if no `src/` changes are detected.
191
+ - `--ai-review` Passed through to the checks script (template supports it).
192
+ - `--auto-push` Generic shim: enable git auto-push after command.
193
+
194
+ ## Command filtering
195
+
196
+ You can control for which Supabase commands checks and hooks should run:
197
+
198
+ - `SHIM_ENFORCE_COMMANDS="functions,db,migration"` to run checks only for those commands
199
+ - `SHIM_HOOK_COMMANDS="functions,db,migration"` to run hooks only for those commands
200
+ - Use `all` or `none` to enable/disable completely
201
+
202
+ Commands are matched by token (e.g. `functions`, `db`, `migration`).
203
+
204
+ Note: If you want checks for `supabase push`, add `push` to `SHIM_ENFORCE_COMMANDS`.
205
+
206
+ For Git, use `SHIM_GIT_ENFORCE_COMMANDS` (default: `push`). You can include `commit,merge,rebase` etc.
207
+
208
+ ## Environment variables
209
+
210
+ - `SHIM_PROJECT_ROOT` Override project root detection.
211
+ - `SHIM_CHECKS_SCRIPT` Path to your checks script (relative to project root or absolute).
212
+ - `SHIM_CHECKS_ARGS` Extra args passed to checks script.
213
+ - `SHIM_CONFIG_FILE` Custom path to config file (default: `.shimwrappercheckrc`).
214
+ - `SHIM_DISABLE_CHECKS=1` Disable checks (same as `--no-checks`).
215
+ - `SHIM_DISABLE_HOOKS=1` Disable hooks (same as `--no-hooks`).
216
+ - `SHIM_AUTO_PUSH=1|0` Enable/disable auto git push after success (default: on).
217
+ - `SHIM_DEFAULT_FUNCTION` Default function name for health/log hooks (default: `server`).
218
+ - `SHIM_ENFORCE_COMMANDS` Comma list for which CLI commands checks should run (`all`, `none`, or e.g. `functions,db,migration`).
219
+ - `SHIM_HOOK_COMMANDS` Comma list for which CLI commands hooks should run (same format).
220
+ - `SHIM_PING_SCRIPT` Override path to health ping script.
221
+ - `SHIM_LOG_SCRIPT` Override path to logs script.
222
+ - `SHIM_GIT_ENFORCE_COMMANDS` Comma list for which git commands checks should run (`push`, `all`, `none`).
223
+ - `SHIM_GIT_CHECKS_SCRIPT` Override checks script for git wrapper.
224
+ - `SHIM_GIT_CHECKS_ARGS` Extra args passed to checks script (git wrapper only).
225
+ - `SHIM_GIT_REAL_BIN` Absolute path to the real git binary (avoids recursion).
226
+ - `SHIM_CLI_ENFORCE_COMMANDS` Generic shim: comma list for which subcommands checks should run.
227
+ - `SHIM_CLI_CHECKS_SCRIPT` Generic shim: override checks script.
228
+ - `SHIM_CLI_CHECKS_ARGS` Generic shim: extra args passed to checks script.
229
+ - `SHIM_CLI_REAL_BIN` Generic shim: absolute path to real CLI binary (avoids recursion).
230
+ - `SHIM_CLI_AUTO_PUSH` Generic shim: enable git auto-push after command (0/1).
231
+ - `SHIM_CLI_PRE_HOOKS` Generic shim: comma list of pre-hook scripts to run.
232
+ - `SHIM_CLI_POST_HOOKS` Generic shim: comma list of post-hook scripts to run.
233
+ - `SHIM_CLI_HOOK_COMMANDS` Generic shim: comma list for which subcommands hooks should run.
234
+
235
+ Network retry (Supabase CLI):
236
+
237
+ - `SUPABASE_RETRY_MAX` Number of retries on network errors (default: 1).
238
+ - `SUPABASE_RETRY_BACKOFF_SECONDS` Comma-separated backoff seconds (default: `5,15`).
239
+ - `SUPABASE_RETRY_EXTRA_ARGS` Extra args added only on retry attempts.
240
+
241
+ Supabase CLI resolution:
242
+
243
+ - `SUPABASE_REAL_BIN` Absolute path to the real Supabase CLI.
244
+ - `SHIM_SUPABASE_BIN` Same as above (alias).
245
+ - `~/.supabase-real-bin` If present, read as real CLI path.
246
+
247
+ Post-deploy hooks:
248
+
249
+ - `SHIM_HEALTH_FUNCTIONS` Comma-separated function names to ping (fallback if not detected).
250
+ - `SHIM_LOG_FUNCTIONS` Comma-separated function names to fetch logs for.
251
+ - `SHIM_LOG_LIMIT` Log lines to fetch (default: 30).
252
+ - `SUPABASE_PROJECT_REF` Project ref for health ping (or `supabase/project-ref`).
253
+ - `SHIM_HEALTH_PATHS` Comma-separated URL paths with `{fn}` placeholder.
254
+
255
+ ## Config file (optional)
256
+
257
+ Create `.shimwrappercheckrc` in your project root to persist settings:
258
+
259
+ ```bash
260
+ SHIM_ENFORCE_COMMANDS="functions,db,migration"
261
+ SHIM_HOOK_COMMANDS="functions,db,migration"
262
+ SHIM_DEFAULT_FUNCTION="server"
263
+ SHIM_AUTO_PUSH=1
264
+ SHIM_CHECKS_ARGS="--no-ai-review"
265
+ ```
266
+
267
+ Note: `.shimwrappercheckrc` is sourced as a shell file.
268
+
269
+ ## Templates
270
+
271
+ - `templates/run-checks.sh` Minimal checks runner; customize for your repo.
272
+ - `templates/ai-code-review.sh` Optional AI review step (Codex default, Cursor fallback).
273
+ - `templates/husky-pre-push` Husky pre-push hook that runs checks.
274
+ - `templates/git-pre-push` Plain git hook version of the same.
275
+
276
+ ## Notes
277
+
278
+ - If the shim is installed locally, it avoids recursion by resolving the real Supabase CLI.
279
+ - If no real CLI is found, it runs `npx --package supabase supabase ...`.
280
+ - The git wrapper should be invoked via `npx git` or `npm run git:checked` to avoid shadowing your system git.
281
+ - Hooks are resolved from your repo first (`scripts/ping-edge-health.sh`, `scripts/fetch-edge-logs.sh`) and fall back to the package scripts.
282
+ - Generic shim hooks default to `scripts/cli-pre-hook.sh` and `scripts/cli-post-hook.sh` if present.
283
+
284
+ ## License
285
+
286
+ UNLICENSED (update if you want a public license).
package/bin/git ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ WRAPPER_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
5
+ exec "$WRAPPER_DIR/scripts/git-checked.sh" "$@"
package/bin/shim ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ WRAPPER_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
5
+ exec "$WRAPPER_DIR/scripts/cli-checked.sh" "$@"
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('../scripts/cli');
package/bin/supabase ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ WRAPPER_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
5
+ exec "$WRAPPER_DIR/scripts/supabase-checked.sh" "$@"
@@ -0,0 +1,7 @@
1
+ {
2
+ "telemetry": {
3
+ "notifiedAt": "1770383569823",
4
+ "anonymousId": "f4adabf96f5c7be2b364a46775c9ffb823e744d1934577fc662aaec287f9cf02",
5
+ "salt": "b9594162f5f71142c4e2987dcd739a3a"
6
+ }
7
+ }
@@ -0,0 +1 @@
1
+ {"type": "commonjs"}
@@ -0,0 +1 @@
1
+ {"version":3,"pages404":true,"caseSensitive":false,"basePath":"","redirects":[{"source":"/:path+/","destination":"/:path+","internal":true,"statusCode":308,"regex":"^(?:/((?:[^/]+?)(?:/(?:[^/]+?))*))/$"}],"headers":[],"dynamicRoutes":[],"staticRoutes":[{"page":"/","regex":"^/(?:/)?$","routeKeys":{},"namedRegex":"^/(?:/)?$"},{"page":"/_not-found","regex":"^/_not\\-found(?:/)?$","routeKeys":{},"namedRegex":"^/_not\\-found(?:/)?$"},{"page":"/agents","regex":"^/agents(?:/)?$","routeKeys":{},"namedRegex":"^/agents(?:/)?$"},{"page":"/config","regex":"^/config(?:/)?$","routeKeys":{},"namedRegex":"^/config(?:/)?$"}],"dataRoutes":[],"rsc":{"header":"RSC","varyHeader":"RSC, Next-Router-State-Tree, Next-Router-Prefetch","prefetchHeader":"Next-Router-Prefetch","didPostponeHeader":"x-nextjs-postponed","contentTypeHeader":"text/x-component","suffix":".rsc","prefetchSuffix":".prefetch.rsc"},"rewrites":[]}
@@ -0,0 +1 @@
1
+ [{"name":"generate-buildid","duration":121,"timestamp":6948914020,"id":4,"parentId":1,"tags":{},"startTime":1770383569821,"traceId":"eb1231321911f71f"},{"name":"load-custom-routes","duration":109,"timestamp":6948914218,"id":5,"parentId":1,"tags":{},"startTime":1770383569821,"traceId":"eb1231321911f71f"},{"name":"create-pages-mapping","duration":77,"timestamp":6948958791,"id":6,"parentId":1,"tags":{},"startTime":1770383569866,"traceId":"eb1231321911f71f"},{"name":"collect-app-paths","duration":1657,"timestamp":6948958882,"id":7,"parentId":1,"tags":{},"startTime":1770383569866,"traceId":"eb1231321911f71f"},{"name":"create-app-mapping","duration":349,"timestamp":6948960570,"id":8,"parentId":1,"tags":{},"startTime":1770383569868,"traceId":"eb1231321911f71f"},{"name":"public-dir-conflict-check","duration":288,"timestamp":6948961063,"id":9,"parentId":1,"tags":{},"startTime":1770383569868,"traceId":"eb1231321911f71f"},{"name":"generate-routes-manifest","duration":879,"timestamp":6948961425,"id":10,"parentId":1,"tags":{},"startTime":1770383569869,"traceId":"eb1231321911f71f"},{"name":"create-dist-dir","duration":77,"timestamp":6948962563,"id":11,"parentId":1,"tags":{},"startTime":1770383569870,"traceId":"eb1231321911f71f"},{"name":"write-routes-manifest","duration":234,"timestamp":6948963636,"id":12,"parentId":1,"tags":{},"startTime":1770383569871,"traceId":"eb1231321911f71f"},{"name":"generate-required-server-files","duration":223,"timestamp":6948963900,"id":13,"parentId":1,"tags":{},"startTime":1770383569871,"traceId":"eb1231321911f71f"},{"name":"next-build","duration":944042,"timestamp":6948865225,"id":1,"tags":{"buildMode":"default","isTurboBuild":"false","version":"14.2.18","isTurbopack":false,"has-custom-webpack-config":"false","use-build-worker":"true"},"startTime":1770383569772,"traceId":"eb1231321911f71f"}]
@@ -0,0 +1,32 @@
1
+ # shimwrappercheck Dashboard
2
+
3
+ Next.js Web UI for shimwrappercheck: status, run checks, edit `.shimwrappercheckrc`, and edit **AGENTS.md**.
4
+
5
+ ## Run locally
6
+
7
+ ```bash
8
+ npm install
9
+ npm run dev
10
+ ```
11
+
12
+ Open http://localhost:3000.
13
+
14
+ ## Deploy (e.g. Vercel)
15
+
16
+ - Set **Root Directory** to `dashboard` (or deploy from repo root and build from `dashboard`).
17
+ - Set env **SHIM_PROJECT_ROOT** to the absolute path of the repo where `.shimwrappercheckrc` and `AGENTS.md` live (required when dashboard runs in a different directory than the project).
18
+
19
+ ## Pages
20
+
21
+ - **Dashboard**: Status (config, AGENTS.md, run-checks script, hooks), button "Nur Checks ausführen", links to Config and AGENTS.md.
22
+ - **Config**: Edit `.shimwrappercheckrc` (raw text).
23
+ - **AGENTS.md**: Edit agent instructions; used by Cursor/Codex. Editable by agents and humans via this UI.
24
+
25
+ ## API
26
+
27
+ - `GET /api/status` – project status (paths, existence of config/AGENTS.md/scripts/hooks).
28
+ - `GET/POST /api/config` – read/write `.shimwrappercheckrc`.
29
+ - `GET/POST /api/agents-md` – read/write `AGENTS.md` (default content if missing).
30
+ - `POST /api/run-checks` – run `scripts/run-checks.sh`, return stdout/stderr/code.
31
+
32
+ All paths resolve from **project root** (parent of `dashboard/` when running locally, or `SHIM_PROJECT_ROOT` when set).
@@ -0,0 +1,88 @@
1
+ /**
2
+ * AGENTS.md editor: edit agent instructions (used by Cursor/Codex agents).
3
+ * Location: app/agents/page.tsx
4
+ */
5
+ "use client";
6
+
7
+ import { useEffect, useState } from "react";
8
+
9
+ export default function AgentsPage() {
10
+ const [raw, setRaw] = useState("");
11
+ const [loading, setLoading] = useState(true);
12
+ const [saving, setSaving] = useState(false);
13
+ const [message, setMessage] = useState<{ type: "success" | "error"; text: string } | null>(null);
14
+ const [exists, setExists] = useState(false);
15
+
16
+ useEffect(() => {
17
+ fetch("/api/agents-md")
18
+ .then((r) => r.json())
19
+ .then((data) => {
20
+ setRaw(data.raw ?? "");
21
+ setExists(data.exists ?? false);
22
+ setLoading(false);
23
+ })
24
+ .catch(() => setLoading(false));
25
+ }, []);
26
+
27
+ const save = () => {
28
+ setSaving(true);
29
+ setMessage(null);
30
+ fetch("/api/agents-md", {
31
+ method: "POST",
32
+ headers: { "Content-Type": "application/json" },
33
+ body: JSON.stringify({ raw }),
34
+ })
35
+ .then((r) => r.json())
36
+ .then((data) => {
37
+ setSaving(false);
38
+ if (data.error) setMessage({ type: "error", text: data.error });
39
+ else {
40
+ setMessage({ type: "success", text: "AGENTS.md gespeichert." });
41
+ setExists(true);
42
+ }
43
+ })
44
+ .catch(() => {
45
+ setSaving(false);
46
+ setMessage({ type: "error", text: "Speichern fehlgeschlagen." });
47
+ });
48
+ };
49
+
50
+ if (loading) {
51
+ return (
52
+ <div className="flex justify-center py-12">
53
+ <span className="loading loading-spinner loading-lg" />
54
+ </div>
55
+ );
56
+ }
57
+
58
+ return (
59
+ <div className="space-y-6">
60
+ <h1 className="text-3xl font-bold">AGENTS.md</h1>
61
+ <p className="text-base-content/80">
62
+ Agent-Anweisungen für Cursor/Codex. Wird von Agents gelesen; hier bearbeitbar. Änderungen gelten sofort.
63
+ </p>
64
+ {!exists && (
65
+ <div className="alert alert-info">
66
+ <span>AGENTS.md existiert noch nicht. Beim Speichern wird sie im Projekt-Root angelegt.</span>
67
+ </div>
68
+ )}
69
+ <textarea
70
+ className="textarea textarea-bordered w-full font-mono text-sm min-h-[400px]"
71
+ value={raw}
72
+ onChange={(e) => setRaw(e.target.value)}
73
+ placeholder="# Agent instructions..."
74
+ spellCheck={false}
75
+ />
76
+ <div className="flex gap-4 items-center">
77
+ <button type="button" className="btn btn-primary" onClick={save} disabled={saving}>
78
+ {saving ? "Speichern…" : "Speichern"}
79
+ </button>
80
+ {message && (
81
+ <span className={message.type === "success" ? "text-success" : "text-error"}>
82
+ {message.text}
83
+ </span>
84
+ )}
85
+ </div>
86
+ </div>
87
+ );
88
+ }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * GET/POST /api/agents-md – read/write AGENTS.md (agent instructions, editable by GUI).
3
+ * Vercel-compatible; uses SHIM_PROJECT_ROOT when deployed.
4
+ */
5
+ import { NextRequest, NextResponse } from "next/server";
6
+ import path from "path";
7
+ import fs from "fs";
8
+ import { getProjectRoot } from "@/lib/projectRoot";
9
+
10
+ const agentsFileName = "AGENTS.md";
11
+
12
+ function getAgentsPath(): string {
13
+ return path.join(getProjectRoot(), agentsFileName);
14
+ }
15
+
16
+ const defaultAgentsContent = `# Agent instructions (shimwrappercheck)
17
+
18
+ This file is used by AI agents (Cursor, Codex, etc.) when working with this repo.
19
+ Edit it here or via the dashboard so agents know how to use the shim and this project.
20
+
21
+ ## Shim usage
22
+
23
+ - Use \`npx supabase ...\` or \`npm run supabase:checked -- ...\` so checks run before deploy.
24
+ - Use \`npx git push\` or \`npm run git:checked -- push\` so checks run before push.
25
+ - Run \`npx shimwrappercheck init\` for setup; \`npx shimwrappercheck install\` for PATH shims.
26
+
27
+ ## Project rules
28
+
29
+ - Keep checks fast; run lint/type/build in scripts/run-checks.sh.
30
+ - AGENTS.md can be edited via the dashboard (Config → AGENTS.md).
31
+ `;
32
+
33
+ export async function GET() {
34
+ try {
35
+ const p = getAgentsPath();
36
+ if (!fs.existsSync(p)) {
37
+ return NextResponse.json({ raw: defaultAgentsContent, exists: false });
38
+ }
39
+ const raw = fs.readFileSync(p, "utf8");
40
+ return NextResponse.json({ raw, exists: true });
41
+ } catch (err) {
42
+ console.error("agents-md get error:", err);
43
+ return NextResponse.json(
44
+ { error: err instanceof Error ? err.message : "Unknown error" },
45
+ { status: 500 }
46
+ );
47
+ }
48
+ }
49
+
50
+ export async function POST(request: NextRequest) {
51
+ try {
52
+ const { raw } = (await request.json()) as { raw?: string };
53
+ if (typeof raw !== "string") {
54
+ return NextResponse.json({ error: "raw string required" }, { status: 400 });
55
+ }
56
+ const p = getAgentsPath();
57
+ const dir = path.dirname(p);
58
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
59
+ fs.writeFileSync(p, raw.endsWith("\n") ? raw : raw + "\n", "utf8");
60
+ return NextResponse.json({ ok: true });
61
+ } catch (err) {
62
+ console.error("agents-md post error:", err);
63
+ return NextResponse.json(
64
+ { error: err instanceof Error ? err.message : "Unknown error" },
65
+ { status: 500 }
66
+ );
67
+ }
68
+ }
@@ -0,0 +1,51 @@
1
+ /**
2
+ * GET/POST /api/config – read/write .shimwrappercheckrc (key=value + comments).
3
+ * Vercel-compatible; uses SHIM_PROJECT_ROOT when deployed.
4
+ */
5
+ import { NextRequest, NextResponse } from "next/server";
6
+ import path from "path";
7
+ import fs from "fs";
8
+ import { getProjectRoot } from "@/lib/projectRoot";
9
+
10
+ const rcFileName = ".shimwrappercheckrc";
11
+
12
+ function getRcPath(): string {
13
+ return path.join(getProjectRoot(), rcFileName);
14
+ }
15
+
16
+ export async function GET() {
17
+ try {
18
+ const p = getRcPath();
19
+ if (!fs.existsSync(p)) {
20
+ return NextResponse.json({ raw: "", exists: false });
21
+ }
22
+ const raw = fs.readFileSync(p, "utf8");
23
+ return NextResponse.json({ raw, exists: true });
24
+ } catch (err) {
25
+ console.error("config get error:", err);
26
+ return NextResponse.json(
27
+ { error: err instanceof Error ? err.message : "Unknown error" },
28
+ { status: 500 }
29
+ );
30
+ }
31
+ }
32
+
33
+ export async function POST(request: NextRequest) {
34
+ try {
35
+ const { raw } = (await request.json()) as { raw?: string };
36
+ if (typeof raw !== "string") {
37
+ return NextResponse.json({ error: "raw string required" }, { status: 400 });
38
+ }
39
+ const p = getRcPath();
40
+ const dir = path.dirname(p);
41
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
42
+ fs.writeFileSync(p, raw.endsWith("\n") ? raw : raw + "\n", "utf8");
43
+ return NextResponse.json({ ok: true });
44
+ } catch (err) {
45
+ console.error("config post error:", err);
46
+ return NextResponse.json(
47
+ { error: err instanceof Error ? err.message : "Unknown error" },
48
+ { status: 500 }
49
+ );
50
+ }
51
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * POST /api/run-checks – run scripts/run-checks.sh and return stdout/stderr.
3
+ * Vercel-compatible; uses SHIM_PROJECT_ROOT. Runs in project root.
4
+ */
5
+ import { NextResponse } from "next/server";
6
+ import path from "path";
7
+ import fs from "fs";
8
+ import { exec } from "child_process";
9
+ import { promisify } from "util";
10
+ import { getProjectRoot } from "@/lib/projectRoot";
11
+
12
+ const execAsync = promisify(exec);
13
+
14
+ type ExecResult = { stdout: string; stderr: string; code?: number };
15
+
16
+ export async function POST() {
17
+ try {
18
+ const root = getProjectRoot();
19
+ const scriptPath = path.join(root, "scripts", "run-checks.sh");
20
+ if (!fs.existsSync(scriptPath)) {
21
+ return NextResponse.json({
22
+ error: "scripts/run-checks.sh not found",
23
+ stdout: "",
24
+ stderr: "",
25
+ code: 1,
26
+ });
27
+ }
28
+ const opts = { cwd: root, maxBuffer: 2 * 1024 * 1024, shell: "/bin/bash" };
29
+ let stdout = "";
30
+ let stderr = "";
31
+ let code = 0;
32
+ try {
33
+ const out = await execAsync(`bash "${scriptPath}"`, opts);
34
+ stdout = out.stdout ?? "";
35
+ stderr = out.stderr ?? "";
36
+ } catch (e: unknown) {
37
+ const err = e as { stdout?: string; stderr?: string; code?: number };
38
+ stdout = err.stdout ?? "";
39
+ stderr = err.stderr ?? (err instanceof Error ? err.message : String(e));
40
+ code = err.code ?? 1;
41
+ }
42
+ return NextResponse.json({ stdout, stderr, code });
43
+ } catch (err) {
44
+ console.error("run-checks error:", err);
45
+ return NextResponse.json(
46
+ {
47
+ stdout: "",
48
+ stderr: err instanceof Error ? err.message : String(err),
49
+ code: 1,
50
+ },
51
+ { status: 200 }
52
+ );
53
+ }
54
+ }