thumbgate 1.19.0 → 1.21.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.
- package/.claude-plugin/marketplace.json +40 -12
- package/.claude-plugin/plugin.json +15 -6
- package/.well-known/mcp/server-card.json +1 -1
- package/README.md +34 -14
- package/adapters/claude/.mcp.json +2 -2
- package/adapters/mcp/server-stdio.js +15 -5
- package/adapters/opencode/opencode.json +1 -1
- package/bin/cli.js +131 -3
- package/bin/postinstall.js +19 -13
- package/config/merge-quality-checks.json +0 -1
- package/config/post-deploy-marketing-pages.json +46 -0
- package/package.json +75 -60
- package/public/agent-manager.html +139 -0
- package/public/compare.html +6 -0
- package/public/guide.html +23 -0
- package/public/index.html +100 -127
- package/public/learn.html +31 -0
- package/public/numbers.html +2 -2
- package/public/pricing.html +345 -0
- package/public/pro.html +3 -22
- package/scripts/auto-promote-gates.js +160 -13
- package/scripts/auto-wire-hooks.js +50 -29
- package/scripts/billing.js +64 -0
- package/scripts/cli-feedback.js +9 -1
- package/scripts/context-manager.js +42 -2
- package/scripts/feedback-loop.js +2 -1
- package/scripts/gates-engine.js +133 -7
- package/scripts/license.js +0 -1
- package/scripts/rate-limiter.js +47 -1
- package/scripts/tool-registry.js +28 -0
- package/scripts/verify-marketing-pages-deployed.js +195 -0
- package/src/api/server.js +514 -239
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "thumbgate-marketplace",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.21.0",
|
|
4
4
|
"owner": {
|
|
5
5
|
"name": "Igor Ganapolsky",
|
|
6
6
|
"email": "ig5973700@gmail.com"
|
|
@@ -8,47 +8,75 @@
|
|
|
8
8
|
"plugins": [
|
|
9
9
|
{
|
|
10
10
|
"name": "thumbgate",
|
|
11
|
-
"description": "
|
|
11
|
+
"description": "One 👎 becomes a hard rule the agent cannot bypass. Captures thumbs-down feedback, distills it into PreToolUse Pre-Action Checks, enforced across every future Claude Code session.",
|
|
12
|
+
"longDescription": "ThumbGate is a tripwire, not a memory layer. When you thumbs-down an agent action — a force-push that overwrote a teammate's commit, a destructive SQL drop, a refactor you already rejected — ThumbGate captures the pattern, distills a one-sentence lesson, and installs it as a PreToolUse block. The next time the agent reaches for the same tool call shape, the hook fires before execution and Claude sees your own words back as the reason.\n\nThe enforcement lives in the hook, not in the model's context, so the agent cannot bypass it by forgetting, by being prompted around it, or by switching sessions. Same rule works in Claude Code, Cursor, Codex, Gemini CLI, Amp, Cline, and OpenCode.\n\n33 pre-action checks shipped (force-push, destructive SQL, mass-delete, npm publish from wrong branch, deploy without verification). Budget enforcement (action count + time limits) prevents runaway agent sessions. NIST / SOC2 / OWASP / CWE compliance tags on every rule for enterprise teams. DPO training-pair export for teams running their own fine-tunes.\n\nFree tier: unlimited local rules, fully offline. Pro ($19/mo): cloud sync across team, dashboard, audit export.",
|
|
12
13
|
"source": {
|
|
13
14
|
"source": "npm",
|
|
14
15
|
"package": "thumbgate"
|
|
15
16
|
},
|
|
16
|
-
"version": "1.
|
|
17
|
+
"version": "1.21.0",
|
|
17
18
|
"author": {
|
|
18
|
-
"name": "Igor Ganapolsky"
|
|
19
|
+
"name": "Igor Ganapolsky",
|
|
20
|
+
"email": "ig5973700@gmail.com",
|
|
21
|
+
"url": "https://thumbgate.ai"
|
|
19
22
|
},
|
|
20
23
|
"homepage": "https://thumbgate-production.up.railway.app",
|
|
21
24
|
"repository": "https://github.com/IgorGanapolsky/ThumbGate",
|
|
22
25
|
"license": "MIT",
|
|
23
26
|
"category": "developer-tools",
|
|
24
27
|
"tags": [
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
28
|
+
"guardrails",
|
|
29
|
+
"pretooluse",
|
|
30
|
+
"hooks",
|
|
31
|
+
"feedback",
|
|
32
|
+
"rlhf",
|
|
33
|
+
"dpo",
|
|
34
|
+
"agent-safety",
|
|
29
35
|
"workflow-hardening"
|
|
30
36
|
],
|
|
31
37
|
"keywords": [
|
|
38
|
+
"guardrails",
|
|
39
|
+
"pretooluse",
|
|
40
|
+
"hooks",
|
|
41
|
+
"feedback",
|
|
42
|
+
"rlhf",
|
|
43
|
+
"dpo",
|
|
44
|
+
"agent-safety",
|
|
45
|
+
"workflow-hardening",
|
|
32
46
|
"claude-desktop",
|
|
33
47
|
"desktop-extension",
|
|
34
48
|
"pre-action-checks",
|
|
35
49
|
"ai-agent-safety",
|
|
36
50
|
"mcp",
|
|
37
|
-
"memory"
|
|
38
|
-
"workflow-hardening"
|
|
51
|
+
"memory"
|
|
39
52
|
],
|
|
53
|
+
"capabilities": {
|
|
54
|
+
"skills": 2,
|
|
55
|
+
"commands": 5,
|
|
56
|
+
"agents": 1,
|
|
57
|
+
"hooks": 3,
|
|
58
|
+
"mcpServer": "thumbgate serve"
|
|
59
|
+
},
|
|
60
|
+
"installCommand": "/plugin install thumbgate@claude-plugins-official",
|
|
40
61
|
"metadata": {
|
|
41
62
|
"author": "Igor Ganapolsky",
|
|
42
63
|
"homepage": "https://thumbgate-production.up.railway.app",
|
|
43
64
|
"license": "MIT",
|
|
44
65
|
"keywords": [
|
|
66
|
+
"guardrails",
|
|
67
|
+
"pretooluse",
|
|
68
|
+
"hooks",
|
|
69
|
+
"feedback",
|
|
70
|
+
"rlhf",
|
|
71
|
+
"dpo",
|
|
72
|
+
"agent-safety",
|
|
73
|
+
"workflow-hardening",
|
|
45
74
|
"claude-desktop",
|
|
46
75
|
"desktop-extension",
|
|
47
76
|
"pre-action-checks",
|
|
48
77
|
"ai-agent-safety",
|
|
49
78
|
"mcp",
|
|
50
|
-
"memory"
|
|
51
|
-
"workflow-hardening"
|
|
79
|
+
"memory"
|
|
52
80
|
],
|
|
53
81
|
"category": "developer-tools"
|
|
54
82
|
}
|
|
@@ -1,22 +1,31 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "thumbgate",
|
|
3
|
-
"description": "
|
|
4
|
-
"version": "1.
|
|
3
|
+
"description": "One 👎 becomes a hard rule the agent cannot bypass. Captures thumbs-down feedback, distills it into PreToolUse Pre-Action Checks, enforced across every future Claude Code session.",
|
|
4
|
+
"version": "1.21.0",
|
|
5
5
|
"author": {
|
|
6
|
-
"name": "Igor Ganapolsky"
|
|
6
|
+
"name": "Igor Ganapolsky",
|
|
7
|
+
"email": "ig5973700@gmail.com",
|
|
8
|
+
"url": "https://thumbgate.ai"
|
|
7
9
|
},
|
|
8
10
|
"homepage": "https://thumbgate-production.up.railway.app",
|
|
9
11
|
"repository": "https://github.com/IgorGanapolsky/ThumbGate",
|
|
10
12
|
"license": "MIT",
|
|
13
|
+
"category": "developer-tools",
|
|
11
14
|
"keywords": [
|
|
15
|
+
"guardrails",
|
|
16
|
+
"pretooluse",
|
|
17
|
+
"hooks",
|
|
18
|
+
"feedback",
|
|
19
|
+
"rlhf",
|
|
20
|
+
"dpo",
|
|
21
|
+
"agent-safety",
|
|
22
|
+
"workflow-hardening",
|
|
12
23
|
"claude-desktop",
|
|
13
24
|
"desktop-extension",
|
|
14
25
|
"mcp",
|
|
15
26
|
"pre-action-checks",
|
|
16
27
|
"ai-agent-safety",
|
|
17
|
-
"memory"
|
|
18
|
-
"guardrails",
|
|
19
|
-
"workflow-hardening"
|
|
28
|
+
"memory"
|
|
20
29
|
],
|
|
21
30
|
"skills": "./skills/",
|
|
22
31
|
"mcpServers": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "thumbgate",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.21.0",
|
|
4
4
|
"description": "ThumbGate — 👍👎 feedback that teaches your AI agent. Thumbs down a mistake, it never happens again.",
|
|
5
5
|
"homepage": "https://thumbgate-production.up.railway.app",
|
|
6
6
|
"transport": "stdio",
|
package/README.md
CHANGED
|
@@ -6,17 +6,23 @@
|
|
|
6
6
|
</a>
|
|
7
7
|
</p>
|
|
8
8
|
|
|
9
|
-
**
|
|
9
|
+
**AI agents repeat mistakes. You pay for every retry.**
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
ThumbGate remembers what went wrong and permanently blocks it before it happens again. One thumbs-down becomes a prevention rule that fires across every session, every agent, every model — before a single token is spent on the repeat.
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
```
|
|
14
|
+
Agent tries: rm -rf tests/
|
|
15
|
+
ThumbGate: ⛔ BLOCKED — "Never delete test directories"
|
|
16
|
+
Pattern matched: rm.*-rf.*tests
|
|
17
|
+
Source: your thumbs-down from last Tuesday
|
|
18
|
+
Tokens spent on this repeat: 0
|
|
19
|
+
```
|
|
16
20
|
|
|
17
|
-
|
|
21
|
+
```bash
|
|
22
|
+
npx thumbgate init # auto-detects your agent, wires hooks, 30 seconds
|
|
23
|
+
```
|
|
18
24
|
|
|
19
|
-
|
|
25
|
+
Works with **Claude Code, Cursor, Codex, Gemini CLI, Amp, Cline, OpenCode** and any MCP-compatible agent. Free tier: 5 active prevention rules. [Pro: $19/mo](https://thumbgate-production.up.railway.app/checkout/pro?utm_source=github&utm_medium=readme) — unlimited rules, dashboard, DPO export.
|
|
20
26
|
|
|
21
27
|
[](https://github.com/IgorGanapolsky/ThumbGate/actions/workflows/ci.yml)
|
|
22
28
|
[](https://www.npmjs.com/package/thumbgate)
|
|
@@ -48,7 +54,7 @@ If someone is not already bought into ThumbGate, do not lead with architecture.
|
|
|
48
54
|
|
|
49
55
|
1. **Show the pain:** open the **[ThumbGate GPT](https://thumbgate-production.up.railway.app/go/gpt?utm_source=github&utm_medium=readme&utm_campaign=first_dollar_activation&cta_id=readme_first_dollar_open_gpt&cta_placement=readme_first_dollar)** and paste the bad answer, risky command, deploy, PR action, or agent plan before it runs again.
|
|
50
56
|
2. **Capture the lesson:** type `thumbs down:` or `thumbs up:` with one concrete sentence. Native ChatGPT rating buttons are not the ThumbGate capture path; typed feedback is.
|
|
51
|
-
3. **Enforce the repeat:** run `npx thumbgate init` where the agent executes so the lesson can become
|
|
57
|
+
3. **Enforce the repeat:** run `npx thumbgate init` where the agent executes so the lesson can become one of your Pre-Action Checks instead of another reminder.
|
|
52
58
|
4. **Upgrade only after proof:** Solo Pro is for the dashboard, DPO export, proof-ready evidence, and higher capture limits after one real blocked repeat. Team starts with the Workflow Hardening Sprint around one repeated failure, one owner, and one proof review.
|
|
53
59
|
|
|
54
60
|
The buying question is simple: **what repeated AI mistake would be worth blocking before the next tool call?**
|
|
@@ -91,8 +97,8 @@ ThumbGate doesn't make your agent smarter. It makes your agent *cheaper to be wr
|
|
|
91
97
|
## Quick Start
|
|
92
98
|
|
|
93
99
|
```bash
|
|
94
|
-
npx thumbgate init
|
|
95
|
-
npx thumbgate capture "Never run DROP on production tables"
|
|
100
|
+
npx thumbgate init # auto-detects your agent, wires everything
|
|
101
|
+
npx thumbgate capture --feedback=down --context="Never run DROP on production tables"
|
|
96
102
|
```
|
|
97
103
|
|
|
98
104
|
That single command creates a prevention rule. Next time any AI agent tries to run `DROP` on production:
|
|
@@ -179,6 +185,19 @@ Each recommendation ships with the benchmark commands to run next: feedback-deri
|
|
|
179
185
|
|
|
180
186
|
Works with **Claude Code, Cursor, Codex, Gemini CLI, Amp, Cline, OpenCode**, and any MCP-compatible agent. Migrating from Roo Code (sunsetting 2026-05-15)? See [`adapters/cline/INSTALL.md`](./adapters/cline/INSTALL.md).
|
|
181
187
|
|
|
188
|
+
### Install scope: machine-wide vs per-project
|
|
189
|
+
|
|
190
|
+
ThumbGate supports two install scopes. Pick once when you install — you can switch later by re-running with the other flag.
|
|
191
|
+
|
|
192
|
+
| Scope | Command | Settings file | Lesson DB + dashboard live in | When to use |
|
|
193
|
+
|-------|---------|---------------|--------------------------------|-------------|
|
|
194
|
+
| **Machine-wide** (default) | `npx thumbgate init` | `~/.claude/settings.json` | `~/.claude/memory/feedback/` | Solo dev — **one shared dashboard across every repo on this machine**. A lesson learned in `repo-A` blocks the same mistake in `repo-B` automatically. |
|
|
195
|
+
| **Per-project** | `npx thumbgate init --project` (in the repo root) | `<repo>/.claude/settings.json` | `<repo>/.claude/memory/feedback/` | Client work, compliance, or multi-tenant — **separate dashboard per repo**, lessons stay isolated, audit trail belongs to the repo. |
|
|
196
|
+
|
|
197
|
+
Both scopes write `mcpServers.thumbgate` + the PreToolUse / UserPromptSubmit / PostToolUse / SessionStart hooks; the only difference is *where*. Machine-wide is the right default for most developers. Switch to `--project` only when you have a reason to keep lessons from bleeding between repos.
|
|
198
|
+
|
|
199
|
+
> Per-project lesson DBs live under each repo's `.claude/memory/feedback/` and **must stay gitignored** — they're a runtime store, not source. ThumbGate's bundled `.gitignore` template handles this.
|
|
200
|
+
|
|
182
201
|
### Status bar proof
|
|
183
202
|
|
|
184
203
|

|
|
@@ -253,10 +272,10 @@ ThumbGate sells three concrete outcomes:
|
|
|
253
272
|
## CLI Reference
|
|
254
273
|
|
|
255
274
|
```bash
|
|
256
|
-
npx thumbgate init
|
|
257
|
-
npx thumbgate doctor
|
|
258
|
-
npx thumbgate capture #
|
|
259
|
-
npx thumbgate lessons
|
|
275
|
+
npx thumbgate init # detect agent, wire hooks
|
|
276
|
+
npx thumbgate doctor # health check
|
|
277
|
+
npx thumbgate capture --feedback=up|down --context="<text>" # capture a signal as a stored lesson
|
|
278
|
+
npx thumbgate lessons # see what's been learned
|
|
260
279
|
npx thumbgate explore # terminal explorer for lessons, checks, stats
|
|
261
280
|
npx thumbgate background-governance # review background-agent run risk
|
|
262
281
|
npx thumbgate model-candidates --workload=dashboard-analysis --provider=openai --json # evaluate GPT-5.5 routing
|
|
@@ -447,6 +466,7 @@ Pro ($19/mo or $149/yr) removes the rule cap and adds history-aware lesson recal
|
|
|
447
466
|
- [**ThumbGate for Federal Agencies**](docs/FEDERAL.md) — pilot-ready posture, NIST 800-53 control mapping, OMB M-24-10 / EO 14110 alignment, ThumbGate-Core gov deployment mode, public/Core boundary invariants. Landing page: [thumbgate.ai/federal](https://thumbgate-production.up.railway.app/federal).
|
|
448
467
|
- [First Dollar Playbook](docs/FIRST_DOLLAR_PLAYBOOK.md) — turning one painful workflow into the next booked pilot
|
|
449
468
|
- [Commercial Truth](docs/COMMERCIAL_TRUTH.md) — pricing, claims, what we don't say
|
|
469
|
+
- [Goal Contracts](docs/GOAL_CONTRACTS.md) — evidence-before-done contracts for multi-agent handoffs
|
|
450
470
|
- [Changeset Strategy](docs/CHANGESET_STRATEGY.md) — release notes and version bump enforcement
|
|
451
471
|
- [Release Confidence](docs/RELEASE_CONFIDENCE.md) — changesets, version checks, proof lanes
|
|
452
472
|
- [Verification Evidence](docs/VERIFICATION_EVIDENCE.md) — proof artifacts
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
"mcpServers": {
|
|
3
3
|
"thumbgate": {
|
|
4
4
|
"command": "npx",
|
|
5
|
-
"args": ["--yes", "--package", "thumbgate@1.
|
|
5
|
+
"args": ["--yes", "--package", "thumbgate@1.21.0", "thumbgate", "serve"]
|
|
6
6
|
}
|
|
7
7
|
},
|
|
8
8
|
"hooks": {
|
|
9
9
|
"preToolUse": {
|
|
10
10
|
"command": "npx",
|
|
11
|
-
"args": ["--yes", "--package", "thumbgate@1.
|
|
11
|
+
"args": ["--yes", "--package", "thumbgate@1.21.0", "thumbgate", "gate-check"]
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
}
|
|
@@ -216,7 +216,7 @@ const {
|
|
|
216
216
|
finalizeSession: finalizeFeedbackSession,
|
|
217
217
|
} = require('../../scripts/feedback-session');
|
|
218
218
|
|
|
219
|
-
const SERVER_INFO = { name: 'thumbgate-mcp', version: '1.
|
|
219
|
+
const SERVER_INFO = { name: 'thumbgate-mcp', version: '1.21.0' };
|
|
220
220
|
const COMMERCE_CATEGORIES = [
|
|
221
221
|
'product_recommendation',
|
|
222
222
|
'brand_compliance',
|
|
@@ -848,12 +848,12 @@ async function callToolInner(name, args) {
|
|
|
848
848
|
});
|
|
849
849
|
}
|
|
850
850
|
case 'verify_claim':
|
|
851
|
-
return toTextResult(verifyClaimEvidence(args.claim));
|
|
851
|
+
return toTextResult(verifyClaimEvidence(args.claim, { goalContract: args.goalContract }));
|
|
852
852
|
case 'require_evidence_for_claim': {
|
|
853
853
|
if (!args.claim || typeof args.claim !== 'string') {
|
|
854
854
|
throw new Error('claim is required and must be a string');
|
|
855
855
|
}
|
|
856
|
-
const verification = verifyClaimEvidence(args.claim);
|
|
856
|
+
const verification = verifyClaimEvidence(args.claim, { goalContract: args.goalContract });
|
|
857
857
|
const mode = args.mode === 'advisory' ? 'advisory' : 'blocking';
|
|
858
858
|
const hasMatchingChecks = Array.isArray(verification.checks) && verification.checks.length > 0;
|
|
859
859
|
const evidenceMissing = hasMatchingChecks && !verification.verified;
|
|
@@ -865,9 +865,18 @@ async function callToolInner(name, args) {
|
|
|
865
865
|
const { recordAuditEvent } = require('../../scripts/audit-trail');
|
|
866
866
|
recordAuditEvent({
|
|
867
867
|
toolName: 'require_evidence_for_claim',
|
|
868
|
-
toolInput: {
|
|
868
|
+
toolInput: {
|
|
869
|
+
claim: args.claim,
|
|
870
|
+
mode,
|
|
871
|
+
sessionId: args.sessionId || null,
|
|
872
|
+
goalContract: verification.goalContract && verification.goalContract.matched
|
|
873
|
+
? verification.goalContract
|
|
874
|
+
: null,
|
|
875
|
+
},
|
|
869
876
|
decision: blocking ? 'deny' : 'allow',
|
|
870
|
-
gateId:
|
|
877
|
+
gateId: verification.goalContract && verification.goalContract.matched
|
|
878
|
+
? 'completion_goal_contract'
|
|
879
|
+
: 'completion_claim',
|
|
871
880
|
message: blocking
|
|
872
881
|
? `Completion claim blocked — missing evidence: ${missingActions.join(', ') || 'unknown'}`
|
|
873
882
|
: `Completion claim verified (${verification.verified ? 'evidence present' : 'no matching gate'})`,
|
|
@@ -882,6 +891,7 @@ async function callToolInner(name, args) {
|
|
|
882
891
|
matchedChecks: hasMatchingChecks,
|
|
883
892
|
missingActions,
|
|
884
893
|
checks: verification.checks,
|
|
894
|
+
goalContract: verification.goalContract,
|
|
885
895
|
sessionId: args.sessionId || null,
|
|
886
896
|
});
|
|
887
897
|
}
|
package/bin/cli.js
CHANGED
|
@@ -141,6 +141,10 @@ function telemetryPing(installId) {
|
|
|
141
141
|
|
|
142
142
|
function proNudge(context) {
|
|
143
143
|
if (process.env.THUMBGATE_NO_NUDGE === '1') return;
|
|
144
|
+
try {
|
|
145
|
+
const { isProTier } = require(path.join(PKG_ROOT, 'scripts', 'rate-limiter'));
|
|
146
|
+
if (isProTier()) return;
|
|
147
|
+
} catch (_) { /* if rate-limiter is unavailable, fall through and nudge */ }
|
|
144
148
|
const messages = [
|
|
145
149
|
`\n 💡 Unlock Pro (${PRO_PRICE_LABEL}): searchable dashboard, DPO export, multi-repo sync\n ${PRO_CHECKOUT_URL}\n`,
|
|
146
150
|
`\n 💡 Pro tip: export your feedback as DPO training pairs to improve your models.\n Get Pro: ${PRO_CHECKOUT_URL}\n`,
|
|
@@ -847,6 +851,12 @@ function capture() {
|
|
|
847
851
|
process.exit(1);
|
|
848
852
|
}
|
|
849
853
|
|
|
854
|
+
const gateAction = (args.action || '').toLowerCase();
|
|
855
|
+
if (gateAction && !['block', 'approve', 'warn'].includes(gateAction)) {
|
|
856
|
+
console.error('Unrecognized --action. Use: block (default), approve, or warn');
|
|
857
|
+
process.exit(1);
|
|
858
|
+
}
|
|
859
|
+
|
|
850
860
|
const result = captureFeedback({
|
|
851
861
|
signal: normalized,
|
|
852
862
|
context: args.context || '',
|
|
@@ -854,6 +864,7 @@ function capture() {
|
|
|
854
864
|
whatToChange: args['what-to-change'],
|
|
855
865
|
whatWorked: args['what-worked'],
|
|
856
866
|
tags: args.tags,
|
|
867
|
+
gateAction: gateAction || undefined,
|
|
857
868
|
});
|
|
858
869
|
|
|
859
870
|
if (result.accepted) {
|
|
@@ -1157,7 +1168,10 @@ function pro() {
|
|
|
1157
1168
|
}
|
|
1158
1169
|
|
|
1159
1170
|
const resolvedKey = resolveProKey();
|
|
1160
|
-
|
|
1171
|
+
// creator-dev legitimately returns {key: '', source: 'creator-dev', plan: 'enterprise'}
|
|
1172
|
+
// when THUMBGATE_DEV_KEY is unset — startLocalProDashboard accepts the empty
|
|
1173
|
+
// key in that case (see pro-local-dashboard.js:141), so launch on source too.
|
|
1174
|
+
if (resolvedKey && (resolvedKey.key || resolvedKey.source === 'creator-dev')) {
|
|
1161
1175
|
return launchDashboard(resolvedKey.key, 'pro_dashboard_launch');
|
|
1162
1176
|
}
|
|
1163
1177
|
|
|
@@ -2299,6 +2313,37 @@ function startApi() {
|
|
|
2299
2313
|
|
|
2300
2314
|
function help() {
|
|
2301
2315
|
const v = pkgVersion();
|
|
2316
|
+
const helpArgs = process.argv.slice(3);
|
|
2317
|
+
const showAll = helpArgs.includes('all')
|
|
2318
|
+
|| helpArgs.includes('--all')
|
|
2319
|
+
|| helpArgs.includes('--full');
|
|
2320
|
+
|
|
2321
|
+
// Default `thumbgate help` shows a curated short list. The full ~70-command
|
|
2322
|
+
// surface lives behind `thumbgate help all` so first-time users aren't hit
|
|
2323
|
+
// with a wall of text. (Pre-2026-05-18 default: dump everything.)
|
|
2324
|
+
if (!showAll) {
|
|
2325
|
+
console.log(`thumbgate v${v} — pre-action checks for AI coding agents`);
|
|
2326
|
+
console.log('');
|
|
2327
|
+
console.log('Common commands:');
|
|
2328
|
+
console.log(' init Detect agent and wire ThumbGate hooks');
|
|
2329
|
+
console.log(' capture --feedback=up|down --context="<text>" Capture a thumbs signal as a stored lesson');
|
|
2330
|
+
console.log(' stats Approval rate, recent trend, blocked-pattern count');
|
|
2331
|
+
console.log(' lessons [query] Search promoted lessons');
|
|
2332
|
+
console.log(' explore Interactive TUI for lessons, gates, stats');
|
|
2333
|
+
console.log(' dashboard Open the local ThumbGate dashboard');
|
|
2334
|
+
console.log(' doctor Audit runtime isolation + bootstrap context');
|
|
2335
|
+
console.log(' pro ThumbGate Pro (dashboard, exports, sync)');
|
|
2336
|
+
console.log(' subscribe <email> Get the 5-min setup guide + weekly tips by email');
|
|
2337
|
+
console.log('');
|
|
2338
|
+
console.log('More:');
|
|
2339
|
+
console.log(' thumbgate help all Full subcommand surface (~70 commands)');
|
|
2340
|
+
console.log(' thumbgate <cmd> --help Per-command flags (where supported)');
|
|
2341
|
+
console.log('');
|
|
2342
|
+
console.log('Docs: https://github.com/IgorGanapolsky/ThumbGate');
|
|
2343
|
+
proNudge();
|
|
2344
|
+
return;
|
|
2345
|
+
}
|
|
2346
|
+
|
|
2302
2347
|
const { groupedCommands, commandHelpLine } = require(path.join(PKG_ROOT, 'scripts', 'cli-schema'));
|
|
2303
2348
|
const groups = groupedCommands();
|
|
2304
2349
|
const GROUP_LABELS = {
|
|
@@ -2310,7 +2355,7 @@ function help() {
|
|
|
2310
2355
|
advanced: 'Advanced',
|
|
2311
2356
|
};
|
|
2312
2357
|
|
|
2313
|
-
console.log(`thumbgate v${v} — pre-action checks for AI coding agents`);
|
|
2358
|
+
console.log(`thumbgate v${v} — pre-action checks for AI coding agents (full command surface)`);
|
|
2314
2359
|
console.log('');
|
|
2315
2360
|
|
|
2316
2361
|
for (const [groupKey, label] of Object.entries(GROUP_LABELS)) {
|
|
@@ -2334,7 +2379,10 @@ function help() {
|
|
|
2334
2379
|
|
|
2335
2380
|
// Legacy and specialist commands kept visible until they graduate into the schema.
|
|
2336
2381
|
console.log('Also available:');
|
|
2337
|
-
console.log(' install-mcp Install MCP server into Claude Code settings
|
|
2382
|
+
console.log(' install-mcp Install MCP server + PreToolUse hooks into Claude Code settings');
|
|
2383
|
+
console.log(' default: machine-wide (~/.claude/settings.json — shared dashboard)');
|
|
2384
|
+
console.log(' --project: per-repo (<cwd>/.claude/settings.json — isolated dashboard)');
|
|
2385
|
+
console.log(' --no-hooks: MCP only, skip hook wiring');
|
|
2338
2386
|
console.log(' cfo Hosted billing summary (local fallback JSON)');
|
|
2339
2387
|
console.log(' billing:setup Generate operator key + print Railway setup instructions');
|
|
2340
2388
|
console.log(' repair-github-marketplace Repair legacy GitHub Marketplace amount mappings');
|
|
@@ -2833,6 +2881,86 @@ switch (COMMAND) {
|
|
|
2833
2881
|
case 'compact':
|
|
2834
2882
|
compact();
|
|
2835
2883
|
break;
|
|
2884
|
+
case 'subscribe': {
|
|
2885
|
+
// Capture an installer's email so we can send the 5-minute setup
|
|
2886
|
+
// guide + weekly tips. Drops to /v1/marketing/install-email on the
|
|
2887
|
+
// hosted endpoint; the server fires sendNewsletterWelcomeEmail via
|
|
2888
|
+
// Resend and persists the address for follow-up.
|
|
2889
|
+
//
|
|
2890
|
+
// Usage:
|
|
2891
|
+
// npx thumbgate subscribe you@company.com
|
|
2892
|
+
// npx thumbgate subscribe --email=you@company.com
|
|
2893
|
+
//
|
|
2894
|
+
// Never prompts interactively — postinstall must stay non-interactive
|
|
2895
|
+
// for CI safety. This is the deliberate opt-in path the banner points
|
|
2896
|
+
// at; if the operator runs it, they want the email.
|
|
2897
|
+
const args = process.argv.slice(3);
|
|
2898
|
+
let email = '';
|
|
2899
|
+
for (const arg of args) {
|
|
2900
|
+
if (arg.startsWith('--email=')) email = arg.slice('--email='.length).trim();
|
|
2901
|
+
else if (!arg.startsWith('--')) email = arg.trim();
|
|
2902
|
+
}
|
|
2903
|
+
if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
|
|
2904
|
+
console.error('Usage: npx thumbgate subscribe <email>');
|
|
2905
|
+
console.error(' npx thumbgate subscribe --email=you@company.com');
|
|
2906
|
+
console.error('');
|
|
2907
|
+
console.error('We send a 5-minute setup guide + weekly tips. One-click unsubscribe.');
|
|
2908
|
+
process.exit(1);
|
|
2909
|
+
}
|
|
2910
|
+
const endpoint = process.env.THUMBGATE_INSTALL_EMAIL_ENDPOINT
|
|
2911
|
+
|| 'https://thumbgate.ai/v1/marketing/install-email';
|
|
2912
|
+
const payload = JSON.stringify({
|
|
2913
|
+
email,
|
|
2914
|
+
source: 'cli_subscribe',
|
|
2915
|
+
installId: (() => {
|
|
2916
|
+
try {
|
|
2917
|
+
const configPath = path.join(CWD, '.thumbgate', 'config.json');
|
|
2918
|
+
if (!fs.existsSync(configPath)) return null;
|
|
2919
|
+
return (JSON.parse(fs.readFileSync(configPath, 'utf8')).installId) || null;
|
|
2920
|
+
} catch { return null; }
|
|
2921
|
+
})(),
|
|
2922
|
+
cliVersion: pkgVersion(),
|
|
2923
|
+
});
|
|
2924
|
+
const url = new URL(endpoint);
|
|
2925
|
+
const transport = url.protocol === 'https:' ? require('node:https') : require('node:http');
|
|
2926
|
+
const req = transport.request({
|
|
2927
|
+
method: 'POST',
|
|
2928
|
+
hostname: url.hostname,
|
|
2929
|
+
port: url.port || (url.protocol === 'https:' ? 443 : 80),
|
|
2930
|
+
path: url.pathname + url.search,
|
|
2931
|
+
headers: {
|
|
2932
|
+
'Content-Type': 'application/json',
|
|
2933
|
+
'Content-Length': Buffer.byteLength(payload),
|
|
2934
|
+
'User-Agent': `thumbgate-cli/${pkgVersion()}`,
|
|
2935
|
+
},
|
|
2936
|
+
timeout: 8000,
|
|
2937
|
+
}, (res) => {
|
|
2938
|
+
let body = '';
|
|
2939
|
+
res.on('data', (chunk) => { body += chunk; });
|
|
2940
|
+
res.on('end', () => {
|
|
2941
|
+
if (res.statusCode >= 200 && res.statusCode < 300) {
|
|
2942
|
+
console.log(`✓ Subscribed ${email}.`);
|
|
2943
|
+
console.log(' Check your inbox in ~30 seconds for the setup guide.');
|
|
2944
|
+
console.log(' Unsubscribe link is in every email.');
|
|
2945
|
+
process.exit(0);
|
|
2946
|
+
} else {
|
|
2947
|
+
console.error(`✗ Subscribe failed: HTTP ${res.statusCode}${body ? ` — ${body.slice(0, 200)}` : ''}`);
|
|
2948
|
+
process.exit(2);
|
|
2949
|
+
}
|
|
2950
|
+
});
|
|
2951
|
+
});
|
|
2952
|
+
req.on('error', (err) => {
|
|
2953
|
+
console.error(`✗ Subscribe failed: ${err.message}`);
|
|
2954
|
+
console.error(' Network issue? Try again, or email igor.ganapolsky@gmail.com directly.');
|
|
2955
|
+
process.exit(3);
|
|
2956
|
+
});
|
|
2957
|
+
req.on('timeout', () => {
|
|
2958
|
+
req.destroy(new Error('timeout after 8000ms'));
|
|
2959
|
+
});
|
|
2960
|
+
req.write(payload);
|
|
2961
|
+
req.end();
|
|
2962
|
+
break;
|
|
2963
|
+
}
|
|
2836
2964
|
case 'checkin': {
|
|
2837
2965
|
// User check-in command — asks how it's going after install
|
|
2838
2966
|
const thumbgateDir = path.join(CWD, '.thumbgate');
|
package/bin/postinstall.js
CHANGED
|
@@ -22,29 +22,35 @@ const {
|
|
|
22
22
|
// This captures UTM attribution in our funnel before handing off to Stripe.
|
|
23
23
|
const PRO_CTA_URL = 'https://thumbgate.ai/go/pro?utm_source=npm&utm_medium=postinstall&utm_campaign=first_dollar';
|
|
24
24
|
const WORKFLOW_SPRINT_URL = 'https://thumbgate.ai/#workflow-sprint-intake';
|
|
25
|
+
const DASHBOARD_URL = 'https://thumbgate.ai/dashboard?utm_source=npm&utm_medium=postinstall&utm_campaign=dashboard_nudge';
|
|
25
26
|
|
|
26
27
|
process.stderr.write(`
|
|
27
28
|
╭─────────────────────────────────────────────────────╮
|
|
28
|
-
│ ThumbGate installed.
|
|
29
|
+
│ ThumbGate installed — 14-day Pro trial active. │
|
|
29
30
|
│ │
|
|
30
|
-
│ Every
|
|
31
|
-
│
|
|
32
|
-
│
|
|
33
|
-
│ on mistakes you've already corrected. │
|
|
31
|
+
│ Every feature unlocked. No limits. No card needed. │
|
|
32
|
+
│ After 14 days, you keep the free tier (5 rules, │
|
|
33
|
+
│ unlimited captures) or upgrade to keep Pro. │
|
|
34
34
|
│ │
|
|
35
|
-
│ Start
|
|
35
|
+
│ Start now: │
|
|
36
36
|
│ npx thumbgate init │
|
|
37
37
|
│ npx thumbgate stats │
|
|
38
|
+
│ │
|
|
39
|
+
│ Get the 5-min setup guide + weekly tips: │
|
|
40
|
+
│ npx thumbgate subscribe you@company.com │
|
|
41
|
+
│ │
|
|
42
|
+
│ See your gates firing live: │
|
|
43
|
+
│ ${DASHBOARD_URL.slice(0, 47).padEnd(47, ' ')} │
|
|
38
44
|
╰─────────────────────────────────────────────────────╯
|
|
39
45
|
|
|
40
|
-
Pro
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
46
|
+
Your 14-day Pro trial includes:
|
|
47
|
+
Unlimited prevention rules (free caps at 5)
|
|
48
|
+
Lesson search + recall across sessions
|
|
49
|
+
DPO export for preference fine-tuning
|
|
50
|
+
Hosted dashboard — no self-hosting needed
|
|
44
51
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
${WORKFLOW_SPRINT_URL}
|
|
52
|
+
After the trial: ${PRO_PRICE_LABEL}
|
|
53
|
+
Upgrade: ${PRO_CTA_URL}
|
|
48
54
|
|
|
49
55
|
Or run: npx thumbgate pro
|
|
50
56
|
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$comment": "Sentinel manifest for post-deploy verification of top-level marketing pages. Each entry is curled against the live production URL after every push to main; if the sentinel string is missing from the response body, the deploy is flagged as broken and the workflow comments on the associated PR. Adding a new top-level marketing page? Add it here so the deploy-verify workflow catches a route regression before a real visitor does. Keep sentinel strings short and stable (visible body copy, not styling classes or hashed assets).",
|
|
3
|
+
"version": 1,
|
|
4
|
+
"pages": [
|
|
5
|
+
{
|
|
6
|
+
"route": "/",
|
|
7
|
+
"sentinel": "Stop paying for the same AI mistake twice",
|
|
8
|
+
"description": "Home page hero (lifeblood — never regress)"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"route": "/pro",
|
|
12
|
+
"sentinel": "ThumbGate Pro",
|
|
13
|
+
"description": "Pro landing page"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"route": "/dashboard",
|
|
17
|
+
"sentinel": "ThumbGate Dashboard",
|
|
18
|
+
"description": "Dashboard demo (already enforced by /dashboard step; included here for symmetry with PR comment surface)"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"route": "/federal",
|
|
22
|
+
"sentinel": "ThumbGate",
|
|
23
|
+
"description": "Federal lead-gen page (SBIR / GSA arrivals)"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"route": "/numbers",
|
|
27
|
+
"sentinel": "ThumbGate",
|
|
28
|
+
"description": "First-party numbers / data transparency page"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"route": "/llm-context.md",
|
|
32
|
+
"sentinel": "## What ThumbGate Is",
|
|
33
|
+
"description": "Canonical declarative summary AI crawlers read"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"route": "/robots.txt",
|
|
37
|
+
"sentinel": "User-agent",
|
|
38
|
+
"description": "Crawl directives (mandatory per Google's 2026-05-15 AI features guide)"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"route": "/sitemap.xml",
|
|
42
|
+
"sentinel": "<urlset",
|
|
43
|
+
"description": "XML sitemap for search-engine discoverability"
|
|
44
|
+
}
|
|
45
|
+
]
|
|
46
|
+
}
|