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
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "shimwrappercheck-dashboard",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "scripts": {
6
+ "dev": "next dev",
7
+ "build": "next build",
8
+ "start": "next start",
9
+ "lint": "next lint"
10
+ },
11
+ "dependencies": {
12
+ "next": "14.2.18",
13
+ "react": "^18.3.1",
14
+ "react-dom": "^18.3.1",
15
+ "daisyui": "^4.12.14",
16
+ "tailwindcss": "^3.4.15"
17
+ },
18
+ "devDependencies": {
19
+ "@types/node": "^22.10.1",
20
+ "@types/react": "^18.3.12",
21
+ "@types/react-dom": "^18.3.1",
22
+ "autoprefixer": "^10.4.20",
23
+ "eslint": "^8.57.0",
24
+ "eslint-config-next": "14.2.18",
25
+ "postcss": "^8.4.49",
26
+ "typescript": "^5.7.2"
27
+ }
28
+ }
@@ -0,0 +1,6 @@
1
+ module.exports = {
2
+ plugins: {
3
+ tailwindcss: {},
4
+ autoprefixer: {},
5
+ },
6
+ };
@@ -0,0 +1,14 @@
1
+ /** @type {import('tailwindcss').Config} */
2
+ module.exports = {
3
+ content: [
4
+ "./app/**/*.{js,ts,jsx,tsx,mdx}",
5
+ "./components/**/*.{js,ts,jsx,tsx,mdx}",
6
+ ],
7
+ theme: {
8
+ extend: {},
9
+ },
10
+ plugins: [require("daisyui")],
11
+ daisyui: {
12
+ themes: ["light", "dark"],
13
+ },
14
+ };
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "lib": ["dom", "dom.iterable", "esnext"],
4
+ "allowJs": true,
5
+ "skipLibCheck": true,
6
+ "strict": true,
7
+ "noEmit": true,
8
+ "esModuleInterop": true,
9
+ "module": "esnext",
10
+ "moduleResolution": "bundler",
11
+ "resolveJsonModule": true,
12
+ "isolatedModules": true,
13
+ "jsx": "preserve",
14
+ "incremental": true,
15
+ "plugins": [{ "name": "next" }],
16
+ "paths": { "@/*": ["./*"] }
17
+ },
18
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
19
+ "exclude": ["node_modules"]
20
+ }
@@ -0,0 +1,79 @@
1
+ # Shim Wrapper Concept (Enforced Checks)
2
+
3
+ ## Why
4
+
5
+ Teams often want a guaranteed flow: change code -> run checks -> deploy/push.
6
+ A shim wrapper ensures checks run even when developers or agents use the CLI directly.
7
+
8
+ ## Core idea
9
+
10
+ - Put a wrapper earlier in PATH (or use local npm bin).
11
+ - The wrapper runs checks first.
12
+ - Only after checks pass, the real CLI runs.
13
+ - Git hooks provide a second safety net.
14
+
15
+ ## Wrapper design
16
+
17
+ 1) Resolve the project root.
18
+ 2) Detect which checks to run based on changed files (e.g. `src/` vs `supabase/functions/`).
19
+ 3) Run a checks script (repo-specific).
20
+ 4) Call the real CLI (not the wrapper).
21
+ 5) Run optional post-deploy hooks (health ping, logs).
22
+ 6) Optionally push commits if ahead of upstream.
23
+
24
+ ## Command filtering
25
+
26
+ You can limit which Supabase commands trigger checks and hooks:
27
+
28
+ - `SHIM_ENFORCE_COMMANDS="functions,db,migration"` to run checks only for these commands.
29
+ - `SHIM_HOOK_COMMANDS="functions,db,migration"` to run hooks only for these commands.
30
+ - Use `all` or `none` to enable/disable completely.
31
+
32
+ Persist these settings in `.shimwrappercheckrc` (or set `SHIM_CONFIG_FILE`).
33
+
34
+ ## Avoiding recursion
35
+
36
+ When the wrapper is called via `npx` or local `node_modules/.bin`, it must not call itself.
37
+ To avoid recursion:
38
+
39
+ - Set `SUPABASE_REAL_BIN` to the real CLI path.
40
+ - Or store the real path in `~/.supabase-real-bin`.
41
+ - If no real CLI is found, use `npx --package supabase supabase ...`.
42
+
43
+ ## Recommended layers
44
+
45
+ - Shim wrapper (this package).
46
+ - Git pre-push hook running the same checks.
47
+ - CI checks for extra safety.
48
+
49
+ ## Typical flows
50
+
51
+ ### Backend repo
52
+
53
+ - `supabase functions deploy <name>`
54
+ - Wrapper runs backend checks
55
+ - Deploy happens only if checks pass
56
+
57
+ ### Frontend repo
58
+
59
+ - `git push`
60
+ - Hook runs lint/test/build
61
+ - Push is blocked on failure
62
+
63
+ ### Mixed repo
64
+
65
+ - Wrapper runs backend checks for deploy
66
+ - Hook runs path-specific checks for push
67
+
68
+ ## Dashboard and AGENTS.md
69
+
70
+ - The **dashboard** (`dashboard/`) is a Next.js Web UI: status, run checks, edit `.shimwrappercheckrc`, and edit **AGENTS.md**.
71
+ - **AGENTS.md** at project root is read by AI agents (Cursor, Codex). It can be edited via the dashboard so agents and humans share one source of truth; agents should respect its content.
72
+
73
+ ## Setup checklist
74
+
75
+ 1) Add checks script (repo-specific).
76
+ 2) Use shim wrapper instead of raw CLI.
77
+ 3) Add a pre-push hook for redundancy.
78
+ 4) Validate PATH (or use `npx supabase`).
79
+ 5) Optionally run the dashboard to manage config and AGENTS.md.
@@ -0,0 +1,159 @@
1
+ # Workflow & Gap Analysis (no code changes yet)
2
+
3
+ This doc describes the **desired workflow**, what **already exists**, and what **still needs to be done**. No code has been changed; this is the plan for when you "come in the door" next.
4
+
5
+ ---
6
+
7
+ ## 1. Desired workflow (your description)
8
+
9
+ ### First-time setup: one CLI command + wizard
10
+
11
+ - User runs **one CLI command** that sets up the whole shimwrapper.
12
+ - A **wizard** runs with questions like:
13
+ - "Do you want this? Do you want that?"
14
+ - Prettier, Lint, snake/processes, authentication where needed
15
+ - AI review → "You need to log in to Codex" (or Cursor)
16
+ - etc.
17
+ - User **confirms** what they want; everything is configured from that.
18
+
19
+ ### Later: change things via GUI
20
+
21
+ - User clicks a **link** (e.g. from CLI output or README) → **graphical surface (dashboard)** opens.
22
+ - In the dashboard:
23
+ - **On/off toggles** per check (e.g. "Don’t run this check").
24
+ - **Grouping**: e.g. "Supabase pushes/deploys" vs "GitHub pushes/deploys".
25
+ - **Which commands** run checks/hooks – configurable, with sensible defaults.
26
+
27
+ ### Presets
28
+
29
+ - **Default preset: "Vibe Code"**
30
+ - Includes: **GitHub** (Git) + **Supabase**, with all relevant commands.
31
+ - User can select this preset and then tweak individual categories/commands.
32
+ - **Custom presets**
33
+ - User can **create new presets** (e.g. "Create new preset").
34
+ - **Drag & drop** providers into a preset (e.g. drag "GitHub" into the new preset).
35
+ - When opening a preset (e.g. "GitHub"), all commands for that provider are listed and can be **toggled on/off**.
36
+ - Presets are the main way to say "which commands" (Supabase vs Git vs both, and which subcommands).
37
+
38
+ ### Summary of desired UX
39
+
40
+ | When | What |
41
+ |------|------|
42
+ | First time | One CLI → wizard → "Want this? Want that?" (Prettier, Lint, AI review, auth hints, etc.) → confirm → full setup |
43
+ | Later | Open dashboard via link → toggles per check, groups (Supabase vs GitHub), presets (Vibe Code default, custom by drag & drop) |
44
+ | Presets | Vibe Code = GitHub + Supabase, all commands; custom presets = drag provider in, then toggle commands |
45
+
46
+ ---
47
+
48
+ ## 2. What we already have
49
+
50
+ ### CLI
51
+
52
+ | Piece | Status | Notes |
53
+ |-------|--------|--------|
54
+ | **Single entry** | ✅ | `npx shimwrappercheck init` sets up shim + config + hooks. |
55
+ | **Wizard (init)** | ✅ | Asks: Supabase shim? Git wrapper? Which commands for checks/hooks? AI review? Codex/Cursor login? run-checks.sh / ai-code-review.sh / Husky or git pre-push. |
56
+ | **Not a single "setup everything" command** | ⚠️ | User must first `npm i -D shimwrappercheck`, then `npx shimwrappercheck init`. So "one command" could mean: one command that does install + init (e.g. `npx shimwrappercheck setup` or `create-shimwrapper`). |
57
+ | **Prettier / Lint / snake in wizard** | ❌ | Init does **not** ask "Do you want Prettier? Lint? Snake?" – it only asks for run-checks.sh template (which already contains lint/build/test). So no explicit Prettier/Lint/snake toggles in the wizard. |
58
+ | **Auth hints** | ✅ | Init offers "log in to Codex" / "Cursor agent login" if AI review is enabled. |
59
+ | **install** | ✅ | `npx shimwrappercheck install` drops PATH shims (supabase, git, shim). |
60
+
61
+ ### Config (today)
62
+
63
+ - **.shimwrappercheckrc**: key=value (SHIM_ENFORCE_COMMANDS, SHIM_HOOK_COMMANDS, SHIM_GIT_ENFORCE_COMMANDS, SHIM_AUTO_PUSH, SHIM_CHECKS_ARGS, etc.).
64
+ - **No presets**: no concept of "Vibe Code" or "custom preset" in config.
65
+ - **No per-check toggles in config**: run-checks.sh has --frontend, --backend, --no-ai-review; config only has SHIM_CHECKS_ARGS (e.g. "--no-ai-review"). So "disable this check" = pass args, not a structured list of enabled checks.
66
+
67
+ ### Dashboard (today)
68
+
69
+ | Feature | Status | Notes |
70
+ |---------|--------|--------|
71
+ | **Open via link** | ✅ | User can run dashboard locally and open in browser; README has the link. No "open dashboard" link printed by CLI after init (could be added). |
72
+ | **Status** | ✅ | Shows: config exists, AGENTS.md, run-checks script, Husky, Git hook, Supabase. |
73
+ | **Run checks** | ✅ | Button "Nur Checks ausführen". |
74
+ | **Edit .shimwrappercheckrc** | ✅ | Config page = raw text editor. |
75
+ | **Edit AGENTS.md** | ✅ | Agents page = raw text editor. |
76
+ | **On/off toggles per check** | ❌ | No UI to enable/disable individual checks (e.g. "run lint", "run AI review"). |
77
+ | **Grouping (Supabase vs GitHub)** | ❌ | No UI grouping "Supabase commands" vs "Git commands". |
78
+ | **Presets** | ❌ | No presets (Vibe Code, custom), no drag & drop. |
79
+ | **"Which commands" per provider** | ❌ | No UI to select which Supabase commands (functions, db, migration, …) or Git commands (push, commit, …) run checks/hooks; that’s only in raw .shimwrappercheckrc. |
80
+
81
+ ### Run-checks and checks
82
+
83
+ - **run-checks.sh**: frontend (lint, check:mock-data, build, test, npm audit, optional Snyk), backend (deno fmt/lint/audit), AI review (Codex/Cursor). No explicit "Prettier" step in template (lint covers style in many setups); no "snake" as a separate step.
84
+ - So: **Prettier / Lint / snake** in the wizard would mean either extending the wizard to ask for them and/or extending run-checks.sh (or a config that run-checks.sh reads) to turn steps on/off.
85
+
86
+ ---
87
+
88
+ ## 3. What it should look like (target)
89
+
90
+ ### First-time flow
91
+
92
+ 1. **One command** (e.g. `npx shimwrappercheck setup` or similar):
93
+ - Ensures package is present (install if needed).
94
+ - Runs wizard.
95
+ 2. **Wizard** (can stay in init, or be invoked by setup):
96
+ - "Do you want Supabase shim? Git (GitHub) wrapper?"
97
+ - "Do you want Prettier / Lint / (snake?) in checks?" (or: "Use default checks (lint, build, test, optional AI review)?")
98
+ - "Do you want AI review? → You’ll need to log in to Codex (or Cursor)." → offer login.
99
+ - Create run-checks.sh, ai-code-review.sh, hooks, package.json scripts, .shimwrappercheckrc.
100
+ - At the end: "To change options later, open the dashboard: [link]."
101
+
102
+ ### Dashboard (target)
103
+
104
+ 1. **Presets**
105
+ - **Default: "Vibe Code"** – GitHub + Supabase, all commands (Supabase: functions, db, migration, …; Git: push, …). User can select this and then refine.
106
+ - **Custom presets**: "Create new preset" → name → **drag & drop** providers (e.g. "GitHub", "Supabase") into the preset. When a provider is in the preset, show its commands with toggles.
107
+ - Preset selection (dropdown or cards): e.g. "Vibe Code" | "My Preset" | "+ New preset".
108
+
109
+ 2. **Grouping**
110
+ - **Supabase** section: list of commands (functions deploy, db push, migration, …) with **on/off** for "run checks" and "run hooks" (or one toggle per command that means "enforce checks for this command").
111
+ - **GitHub (Git)** section: list of commands (push, commit, merge, rebase, …) with on/off for "run checks".
112
+
113
+ 3. **Checks**
114
+ - **On/off toggles** for checks that run inside run-checks.sh (or equivalent):
115
+ - e.g. Lint, Prettier, Build, Test, npm audit, Snyk, Backend (deno fmt/lint/audit), AI review.
116
+ - Optional: "Authentication: Codex / Cursor" with hint "Run `codex login` or `agent login` if not done."
117
+
118
+ 4. **Link from CLI**
119
+ - After init/setup: print "Dashboard: http://localhost:3000 (run from dashboard/: npm run dev)" or a stable URL if deployed.
120
+
121
+ ### Data model (for presets and toggles)
122
+
123
+ - **Current**: .shimwrappercheckrc (flat key=value).
124
+ - **Target** (conceptual):
125
+ - **Presets**: list of presets; each preset has a name and a set of "providers" (Supabase, Git) and per-provider "commands" (which subcommands get checks/hooks).
126
+ - **Active preset** or "current config" derived from one preset + overrides.
127
+ - **Checks**: list of check types (lint, prettier, build, test, ai-review, …) with on/off. This could stay in .shimwrappercheckrc as new keys (e.g. SHIM_CHECK_LINT=1, SHIM_CHECK_AI_REVIEW=1) or a small JSON that run-checks.sh or the shim reads.
128
+
129
+ So we need:
130
+ - A way to **store presets** (e.g. JSON in repo or in .shimwrappercheckrc include, or a new file like `.shimwrappercheck-presets.json`).
131
+ - A way to **map preset + toggles** to existing env vars (SHIM_ENFORCE_COMMANDS, SHIM_HOOK_COMMANDS, SHIM_GIT_ENFORCE_COMMANDS, SHIM_CHECKS_ARGS) so the existing bins don’t need a full rewrite.
132
+
133
+ ---
134
+
135
+ ## 4. What still has to be done (concise)
136
+
137
+ | # | Area | To do |
138
+ |---|------|--------|
139
+ | 1 | **CLI: single entry** | Add a single command (e.g. `npx shimwrappercheck setup`) that installs package if needed and runs init wizard. |
140
+ | 2 | **Wizard: Prettier / Lint / snake** | Extend init (or setup) to ask "Prettier? Lint? Snake?" (or a small set of check categories) and write run-checks.sh or config so those run/skip. |
141
+ | 3 | **Wizard: auth** | Keep current "log in to Codex / Cursor" prompts; optionally print dashboard link at end. |
142
+ | 4 | **Dashboard: presets** | Introduce presets (data model + storage). Default preset "Vibe Code" = GitHub + Supabase, all commands. UI: select preset, "Create new preset", drag & drop providers into preset. |
143
+ | 5 | **Dashboard: grouping** | Supabase section (commands + toggles), GitHub section (commands + toggles). Each command has "run checks" on/off (and optionally "run hooks" for Supabase). |
144
+ | 6 | **Dashboard: check toggles** | On/off for: Lint, Prettier, Build, Test, (Snyk?), Backend checks, AI review. Persist to config / run-checks args so run-checks.sh respects them. |
145
+ | 7 | **Config ↔ presets** | When user selects preset or toggles, write .shimwrappercheckrc (and optional presets file) so existing shim bins work without change. |
146
+ | 8 | **CLI → dashboard link** | After init/setup, print dashboard URL (local or deployed). |
147
+
148
+ ---
149
+
150
+ ## 5. Suggested order (when you implement)
151
+
152
+ 1. **Presets data model** (file format + default "Vibe Code" preset).
153
+ 2. **Dashboard: Presets UI** (select preset, show Supabase vs Git groups, command toggles) and **map to .shimwrappercheckrc**.
154
+ 3. **Dashboard: Check toggles** (lint, prettier, build, test, AI review, …) and **map to SHIM_CHECKS_ARGS or run-checks config**.
155
+ 4. **Dashboard: Custom presets** (create new, drag & drop providers).
156
+ 5. **CLI: setup command** (install + init) and **wizard: Prettier/Lint/snake** (if you want them in the wizard).
157
+ 6. **CLI: print dashboard link** at end of init/setup.
158
+
159
+ No code has been changed in this repo; the above is the plan for when you start implementing.
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "shimwrappercheck",
3
+ "version": "0.2.0",
4
+ "description": "Supabase CLI shim wrapper that enforces checks before deploy/push. Dashboard, presets, AGENTS.md.",
5
+ "license": "MIT",
6
+ "bin": {
7
+ "supabase": "bin/supabase",
8
+ "shimwrappercheck": "bin/shimwrappercheck",
9
+ "git": "bin/git",
10
+ "shim": "bin/shim"
11
+ },
12
+ "files": [
13
+ "bin",
14
+ "scripts",
15
+ "templates",
16
+ "docs",
17
+ "dashboard",
18
+ "README.md",
19
+ "AGENTS.md"
20
+ ],
21
+ "engines": {
22
+ "node": ">=18"
23
+ }
24
+ }
@@ -0,0 +1,307 @@
1
+ #!/usr/bin/env bash
2
+ # Generic CLI shim wrapper: run checks (optional), then call the real CLI.
3
+ set -euo pipefail
4
+
5
+ WRAPPER_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
6
+
7
+ resolve_project_root() {
8
+ if [[ -n "${SHIM_PROJECT_ROOT:-}" ]]; then
9
+ echo "$SHIM_PROJECT_ROOT"
10
+ return
11
+ fi
12
+ if command -v git >/dev/null 2>&1; then
13
+ local root
14
+ root="$(git rev-parse --show-toplevel 2>/dev/null || true)"
15
+ if [[ -n "$root" ]]; then
16
+ echo "$root"
17
+ return
18
+ fi
19
+ fi
20
+ pwd
21
+ }
22
+
23
+ PROJECT_ROOT="$(resolve_project_root)"
24
+ cd "$PROJECT_ROOT"
25
+
26
+ CONFIG_FILE="${SHIM_CONFIG_FILE:-$PROJECT_ROOT/.shimwrappercheckrc}"
27
+ if [[ -f "$CONFIG_FILE" ]]; then
28
+ # shellcheck disable=SC1090
29
+ source "$CONFIG_FILE"
30
+ fi
31
+
32
+ ARGS_IN=("$@")
33
+ ARGS_TEXT_RAW=" ${*:-} "
34
+ CLI_NAME=""
35
+ CLI_ARGS=()
36
+ CHECKS_PASSTHROUGH=()
37
+
38
+ RUN_CHECKS=true
39
+ CHECKS_ONLY=false
40
+ FORCE_FRONTEND=false
41
+ RUN_PUSH=false
42
+
43
+ matches_command_list() {
44
+ local list="$1"
45
+ local text="$2"
46
+
47
+ list="$(echo "$list" | tr '[:upper:]' '[:lower:]')"
48
+ text="$(echo "$text" | tr '[:upper:]' '[:lower:]')"
49
+
50
+ if [[ -z "$list" ]] || [[ "$list" == "all" ]]; then
51
+ return 0
52
+ fi
53
+ if [[ "$list" == "none" ]]; then
54
+ return 1
55
+ fi
56
+
57
+ IFS=',' read -r -a items <<< "$list"
58
+ for item in "${items[@]}"; do
59
+ item="$(echo "$item" | xargs)"
60
+ [[ -z "$item" ]] && continue
61
+ if [[ "$text" == *" $item "* ]]; then
62
+ return 0
63
+ fi
64
+ done
65
+ return 1
66
+ }
67
+
68
+ # Parse args: allow either `shim <cli> ...` or `shim --cli <cli> -- ...`
69
+ consume_cli=false
70
+ pass_through=false
71
+ for arg in "${ARGS_IN[@]}"; do
72
+ if [[ "$arg" == "--" ]]; then
73
+ pass_through=true
74
+ continue
75
+ fi
76
+
77
+ if [[ "$pass_through" == true ]]; then
78
+ if [[ -z "$CLI_NAME" ]]; then
79
+ CLI_NAME="$arg"
80
+ else
81
+ CLI_ARGS+=("$arg")
82
+ fi
83
+ continue
84
+ fi
85
+
86
+ if [[ -z "$CLI_NAME" ]] && [[ "$arg" == "--cli" ]]; then
87
+ consume_cli=true
88
+ continue
89
+ fi
90
+
91
+ if [[ "$consume_cli" == true ]] && [[ -z "$CLI_NAME" ]]; then
92
+ CLI_NAME="$arg"
93
+ consume_cli=false
94
+ continue
95
+ fi
96
+
97
+ if [[ -z "$CLI_NAME" ]] && [[ "$arg" != -* ]]; then
98
+ CLI_NAME="$arg"
99
+ continue
100
+ fi
101
+
102
+ case "$arg" in
103
+ --no-checks) RUN_CHECKS=false ;;
104
+ --checks-only) CHECKS_ONLY=true ;;
105
+ --no-ai-review|--ai-review) CHECKS_PASSTHROUGH+=("$arg") ;;
106
+ --with-frontend) FORCE_FRONTEND=true ;;
107
+ --no-push) RUN_PUSH=false ;;
108
+ --auto-push) RUN_PUSH=true ;;
109
+ *) CLI_ARGS+=("$arg") ;;
110
+ esac
111
+ done
112
+
113
+ [[ -n "${SHIM_DISABLE_CHECKS:-}" ]] && RUN_CHECKS=false
114
+ if [[ -n "${SHIM_CLI_AUTO_PUSH:-}" ]]; then
115
+ case "${SHIM_CLI_AUTO_PUSH}" in
116
+ 1|true|TRUE|yes|YES) RUN_PUSH=true ;;
117
+ 0|false|FALSE|no|NO) RUN_PUSH=false ;;
118
+ esac
119
+ fi
120
+
121
+ if [[ -z "$CLI_NAME" ]] && [[ "$CHECKS_ONLY" != true ]]; then
122
+ echo "No CLI provided. Usage: shim <cli> [shim flags] <args>" >&2
123
+ echo "or: shim --cli <cli> -- <args>" >&2
124
+ exit 1
125
+ fi
126
+
127
+ ARGS_TEXT=" ${CLI_ARGS[*]:-} "
128
+ if [[ "$CHECKS_ONLY" != true ]]; then
129
+ enforce_list="${SHIM_CLI_ENFORCE_COMMANDS:-${SHIM_ENFORCE_COMMANDS:-all}}"
130
+ if ! matches_command_list "$enforce_list" "$ARGS_TEXT"; then
131
+ RUN_CHECKS=false
132
+ fi
133
+ fi
134
+
135
+ should_run_hooks=false
136
+ hook_list="${SHIM_CLI_HOOK_COMMANDS:-all}"
137
+ if matches_command_list "$hook_list" "$ARGS_TEXT"; then
138
+ should_run_hooks=true
139
+ fi
140
+
141
+ resolve_hook_list() {
142
+ local list="$1"
143
+ local default_name="$2"
144
+ local resolved=()
145
+
146
+ if [[ -n "$list" ]]; then
147
+ IFS=',' read -r -a items <<< "$list"
148
+ for item in "${items[@]}"; do
149
+ item="$(echo "$item" | xargs)"
150
+ [[ -z "$item" ]] && continue
151
+ if [[ "$item" != /* ]]; then
152
+ item="$PROJECT_ROOT/$item"
153
+ fi
154
+ resolved+=("$item")
155
+ done
156
+ elif [[ -n "$default_name" ]] && [[ -f "$PROJECT_ROOT/scripts/$default_name" ]]; then
157
+ resolved+=("$PROJECT_ROOT/scripts/$default_name")
158
+ fi
159
+
160
+ printf '%s\n' "${resolved[@]}"
161
+ }
162
+
163
+ resolve_checks_script() {
164
+ local script="${SHIM_CLI_CHECKS_SCRIPT:-}"
165
+ if [[ -n "$script" ]]; then
166
+ if [[ "$script" != /* ]]; then
167
+ script="$PROJECT_ROOT/$script"
168
+ fi
169
+ echo "$script"
170
+ return
171
+ fi
172
+ script="${SHIM_CHECKS_SCRIPT:-}"
173
+ if [[ -n "$script" ]]; then
174
+ if [[ "$script" != /* ]]; then
175
+ script="$PROJECT_ROOT/$script"
176
+ fi
177
+ echo "$script"
178
+ return
179
+ fi
180
+ local candidates=("scripts/run-checks.sh" "scripts/shim-checks.sh")
181
+ for candidate in "${candidates[@]}"; do
182
+ if [[ -f "$PROJECT_ROOT/$candidate" ]]; then
183
+ echo "$PROJECT_ROOT/$candidate"
184
+ return
185
+ fi
186
+ done
187
+ echo ""
188
+ }
189
+
190
+ if [[ "$RUN_CHECKS" = true ]]; then
191
+ run_frontend=false
192
+ run_backend=false
193
+ run_ai_review=true
194
+
195
+ changed_files=""
196
+ if command -v git >/dev/null 2>&1; then
197
+ unstaged=$(git diff --name-only --diff-filter=ACMR || true)
198
+ staged=$(git diff --name-only --cached --diff-filter=ACMR || true)
199
+ changed_files=$(printf "%s\n%s\n" "$unstaged" "$staged")
200
+ fi
201
+
202
+ if [[ -n "$changed_files" ]]; then
203
+ echo "$changed_files" | grep -q '^src/' && run_frontend=true
204
+ echo "$changed_files" | grep -q '^supabase/functions/' && run_backend=true
205
+ fi
206
+
207
+ if [[ "$FORCE_FRONTEND" = true ]] || [[ "$ARGS_TEXT_RAW" == *" --with-frontend "* ]]; then
208
+ run_frontend=true
209
+ fi
210
+
211
+ if [[ "$ARGS_TEXT_RAW" == *" --no-ai-review "* ]]; then
212
+ run_ai_review=false
213
+ fi
214
+ if [[ -n "${SKIP_AI_REVIEW:-}" ]]; then
215
+ run_ai_review=false
216
+ fi
217
+
218
+ if [[ "$run_frontend" = true ]] || [[ "$run_backend" = true ]]; then
219
+ CHECKS_SCRIPT="$(resolve_checks_script)"
220
+ if [[ -n "$CHECKS_SCRIPT" ]]; then
221
+ CHECKS_ARGS=()
222
+ if [[ -n "${SHIM_CLI_CHECKS_ARGS:-}" ]]; then
223
+ read -r -a CHECKS_ARGS <<< "${SHIM_CLI_CHECKS_ARGS}"
224
+ elif [[ -n "${SHIM_CHECKS_ARGS:-}" ]]; then
225
+ read -r -a CHECKS_ARGS <<< "${SHIM_CHECKS_ARGS}"
226
+ fi
227
+ [[ "$run_frontend" = true ]] && CHECKS_ARGS+=(--frontend)
228
+ [[ "$run_backend" = true ]] && CHECKS_ARGS+=(--backend)
229
+ [[ "$run_ai_review" = false ]] && CHECKS_ARGS+=(--no-ai-review)
230
+ CHECKS_ARGS+=("${CHECKS_PASSTHROUGH[@]}")
231
+ bash "$CHECKS_SCRIPT" "${CHECKS_ARGS[@]}"
232
+ else
233
+ echo "Shim checks: no checks script found; skipping." >&2
234
+ fi
235
+ fi
236
+ fi
237
+
238
+ if [[ "$CHECKS_ONLY" = true ]]; then
239
+ exit 0
240
+ fi
241
+
242
+ REAL_BIN="${SHIM_CLI_REAL_BIN:-${SHIM_REAL_BIN:-}}"
243
+ if [[ -z "$REAL_BIN" ]]; then
244
+ REAL_BIN="$(command -v "$CLI_NAME" || true)"
245
+ fi
246
+ if [[ -n "$REAL_BIN" ]] && { [[ "$REAL_BIN" == *"node_modules"* ]] || [[ "$REAL_BIN" == "$WRAPPER_DIR"* ]]; }; then
247
+ REAL_BIN=""
248
+ fi
249
+
250
+ if [[ -z "$REAL_BIN" ]]; then
251
+ echo "Real binary for '$CLI_NAME' not found. Set SHIM_CLI_REAL_BIN." >&2
252
+ exit 1
253
+ fi
254
+
255
+ pre_hooks="$(resolve_hook_list "${SHIM_CLI_PRE_HOOKS:-}" "cli-pre-hook.sh")"
256
+ post_hooks="$(resolve_hook_list "${SHIM_CLI_POST_HOOKS:-}" "cli-post-hook.sh")"
257
+
258
+ if [[ "$should_run_hooks" = true ]] && [[ -n "$pre_hooks" ]]; then
259
+ while IFS= read -r hook; do
260
+ [[ -z "$hook" ]] && continue
261
+ if [[ -f "$hook" ]]; then
262
+ bash "$hook" "$CLI_NAME" "${CLI_ARGS[@]}"
263
+ else
264
+ echo "Pre-hook not found: $hook" >&2
265
+ fi
266
+ done <<< "$pre_hooks"
267
+ fi
268
+
269
+ set +e
270
+ if [[ "$(basename "$REAL_BIN")" == "$CLI_NAME" ]]; then
271
+ "$REAL_BIN" "${CLI_ARGS[@]}"
272
+ else
273
+ "$REAL_BIN" "$CLI_NAME" "${CLI_ARGS[@]}"
274
+ fi
275
+ CLI_RC=$?
276
+ set -e
277
+
278
+ if [[ $CLI_RC -ne 0 ]]; then
279
+ exit $CLI_RC
280
+ fi
281
+
282
+ if [[ "$should_run_hooks" = true ]] && [[ -n "$post_hooks" ]]; then
283
+ while IFS= read -r hook; do
284
+ [[ -z "$hook" ]] && continue
285
+ if [[ -f "$hook" ]]; then
286
+ bash "$hook" "$CLI_NAME" "${CLI_ARGS[@]}" || true
287
+ else
288
+ echo "Post-hook not found: $hook" >&2
289
+ fi
290
+ done <<< "$post_hooks"
291
+ fi
292
+
293
+ if [[ "$RUN_PUSH" = true ]] && command -v git >/dev/null 2>&1; then
294
+ if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
295
+ if git rev-parse --abbrev-ref --symbolic-full-name @{u} >/dev/null 2>&1; then
296
+ ahead=$(git rev-list --count @{u}..HEAD)
297
+ if [[ "${ahead:-0}" -gt 0 ]]; then
298
+ echo "Pushing commits to remote..."
299
+ git push
300
+ else
301
+ echo "No commits to push."
302
+ fi
303
+ else
304
+ echo "No upstream configured; skipping git push."
305
+ fi
306
+ fi
307
+ fi
package/scripts/cli.js ADDED
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env node
2
+ const path = require('path');
3
+
4
+ const cmd = process.argv[2];
5
+
6
+ if (cmd === 'setup') {
7
+ require(path.join(__dirname, 'setup'));
8
+ return;
9
+ }
10
+
11
+ if (!cmd || cmd === 'init') {
12
+ require(path.join(__dirname, 'init'));
13
+ return;
14
+ }
15
+
16
+ if (cmd === 'install') {
17
+ require(path.join(__dirname, 'install'));
18
+ return;
19
+ }
20
+
21
+ console.error('Unknown command:', cmd);
22
+ console.error('Usage: shimwrappercheck [setup|init|install]');
23
+ process.exit(1);