Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,15 @@ Azure, `git push`, `npm publish`.
digest in `digest.mjs` (failed checks with at most three evidence lines each, and the app's name, framework,
address, payment provider and host): no source code, no file contents, no secret's value (a check that finds a key
reports its kind, file and line). It is shown before the first send for a project, `--no-model` sends nothing, and
the server stores a count per account and day and nothing else. Sending more than the digest holds, storing a
digest or an answer, or changing who the digest goes to needs the owner's OK and a change to PRIVACY.md, like
rule 8. The checks are free for everyone; a plan decides how many items of the model's plan are shown and how
many runs a day (`billing/plans.json` `suggestions`).
the server stores a count per account and day. Changed by the owner on 2026-11-12: the digest also holds what the
site says it is about (its title and meta description, 300 characters); besides ordering the checks, the model
writes its own ideas for the app and website design ideas, each inspired by a real site it names (the server drops
one whose site does not answer), always printed as the model's ideas, never as measured; and the last answer per
account and app is kept (`suggest_results`, migration 0019) so that Free is shown the same answer again until it
pays, and Pro reads it. Free (`suggestions.shown` 1) sees the first item and the counts of the rest, ideas and
designs included, which are never sent to it. Storing the digest, sending more than it holds, or changing who it
goes to needs the owner's OK and a change to PRIVACY.md, like rule 8. The measured checks run for everyone; a plan
decides how many items of the answer are shown and how many runs a day (`billing/plans.json` `suggestions`).

12. **A terminal does what its approval page lists, and `genclass ask` sends a question, never code**
(`telemetry-worker/src/cli.ts`, `src/ask.ts`, `src/account-pages.ts`; owner request, 2026-11-12). Every route under
Expand All @@ -151,7 +156,9 @@ Azure, `git push`, `npm publish`.
deletes an app or the account. `genclass ask` sends the question and at most three earlier turns; the server adds
a digest of the numbers that account's dashboard shows (`appDigest`) and gives both to the model, which is told to
answer from the numbers only and that page names and labels are data. Nothing of a question or an answer is
stored or logged, and it takes one of the plan's model runs a day, shared with `suggest`. `genclass fix` builds
stored or logged, and it takes one of the plan's model runs a day, shared with `suggest`. Since 2026-11-12 asking
is Pro's (`billing/plans.json` entitlement `ask`), and Free sees the totals only (entitlement `problems`: the
problem lists, pages, activity and fix prompts are left out of its stats, `src/dashboard.ts` stripProblems). `genclass fix` builds
its prompt on the person's machine and starts their own agent on a key press: nothing in this repository fixes
code by itself. Sending the model more than the digest holds, storing a question or an answer, or letting a
terminal do something the approval page does not list needs the owner's OK and a change to PRIVACY.md.
Expand Down
18 changes: 11 additions & 7 deletions PRIVACY.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ and invite links.

## Paid plans, payments and Stripe

Free costs nothing, Team is sold on genclass.dev per project (since 12 November 2026; per developer from 11 November), and Enterprise is agreed by
Free costs nothing, Pro (named Team until 12 November 2026) is sold on genclass.dev per project (since 12 November 2026; per developer from 11 November), and Enterprise is agreed by
email. A plan decides what your dashboard shows, never what is collected: an app that turned visitor analytics on has
them counted on Free too, and they show once its plan includes them. A paid plan (Team; the Individual plan was one
until 22 October 2026) is paid through Stripe, which processes payments
Expand Down Expand Up @@ -243,7 +243,7 @@ its export already hold; nothing new is collected or stored for them. A destinat
`genclass connections add` is not shown, is sent to genclass.dev once over HTTPS, is stored encrypted there like one
typed on the dashboard, and is not kept on the developer's machine.

**`genclass ask`** answers a question about an app in words. The question, and at most three earlier questions and
**`genclass ask`** (the Pro plan) answers a question about an app in words. The question, and at most three earlier questions and
answers of the same sitting, leave the developer's machine. On genclass.dev we add the numbers that account's
dashboard already shows for the app and period (page paths, kinds of problem, counts, what the runtime did, what the
coding agent reported and, where the plan has visitor analytics, visits, sources, devices, countries and the names
Expand All @@ -269,15 +269,19 @@ repository answers "not found" and is left as it is.
should not exist, and DNS lookups for its mail records. They go to that site, not to us.
- **A digest sent to genclass.dev, to get a plan written for the app.** It holds the checks that failed (each with
its title and at most three short evidence lines, such as a status code, a page title or a file name and line
number) and five things about the app: its name, framework, address, payment provider and host. It holds no source
number), and six things about the app: its name, framework, address, what its site says it is about (the home
page's title and description, at most 300 characters), payment provider and host. It holds no source
code, no file contents, no environment values and no secrets; where a check finds a key in a file, the evidence is
the kind of key, the file and the line, never the key. The command shows this before the first time it sends it
for a project, and `--no-model` sends nothing.

We pass the digest to a language model (OpenAI's API) to order the failed checks and word the reasons, and return
its answer. We do not store the digest or the answer and do not log them. We keep one number: how many plans an
account asked for on a day, for 3 days, to hold each plan's daily limit. OpenAI processes the digest under its API
terms. Nothing from a digest is used to train GenClass's own model.
We pass the digest to a language model (OpenAI's API) to order the failed checks and word the reasons, to suggest
its own ideas for the app and website designs inspired by real sites (we check that each site it names answers), and
return its answer. We do not store or log the digest. Since 12 November 2026 we keep the last answer for each app of
an account (the ordered checks with their reasons, the ideas and the designs, not the digest), so the Free plan can
show the same answer again and a paid plan can show all of it; it is replaced by the next answer and deleted with the
account. We also keep how many plans an account asked for on a day, for 3 days, to hold each plan's daily limit.
OpenAI processes the digest under its API terms. Nothing from a digest is used to train GenClass's own model.

## Where it goes and how long we keep it

Expand Down
31 changes: 18 additions & 13 deletions billing/plans.json
Original file line number Diff line number Diff line change
@@ -1,40 +1,40 @@
{
"_about": "The one place GenClass plans are defined. telemetry-worker/src/plans.ts imports this file (limits, entitlements, Stripe lookup keys, the billing page) and genclass.dev's site reads it (the pricing page). Three plans since version 3 (2026-11-11): Free, Team and Enterprise; since version 4 (2026-11-12) a plan belongs to a project, not to an account. Free is what finds, shows and fixes the problems: the open-source runtime with every mode and its on-device model, the coding-agent loop on the developer's machine, the dashboard's problems for an account's first 3 projects (the last 7 days shown; a 4th project on Free is locked until it has a plan), and 100 problems fixed live a month per project (limits.live_fixes_per_month; past it the runtime is told to observe only until the month ends) and genclass-dev[bot] on public repositories. Team is sold per project (per_project true: one Stripe subscription of quantity 1 per project, its metadata naming the project; everyone on the account's team sees it; telemetry-worker/src/stripe.ts) and adds what a team uses: genclass-dev[bot] on private repositories, visitor analytics, forwarding, export, 90 days of history and members. Enterprise is agreed by email: a null monthly price means the plan is not sold on the site, and an account gets it from GenClass's own grant (accounts.comp_until, set by hand to the end of the agreement; accounts.comp_plan names the plan granted, grant_plan when it is empty). The classifier a person from GenClass trains is in Enterprise only. retired_plans lists the plan ids GenClass sold before (Pro and Custom until 2026-10-19, Individual until 2026-10-22): their Stripe products and prices stay GenClass's own, so a subscription to one is still cancelled with its account, opens Manage billing and is reported to the owner while it bills, but it gives no plan (it reads as Free). The worker's Stripe code and scripts/stripe-setup.mjs sell any plan given a monthly price above 0, its stripe_lookup_keys and a stripe_tax_code. Prices are US cents (per project for a per_project plan, per seat for a per_seat plan); a null yearly price means no yearly option. limits.apps null means no plan limit (the worker still caps an account at 200 apps against abuse); limits.seats is how many people a plan that is not per_seat holds (null: no limit); limits.history_days is what the dashboard shows, and data is never deleted before 90 days whatever the plan, so the longer history is there the moment an account upgrades. Ingest never depends on the plan: an app's visitor analytics are counted while its plan leaves them out, and shown once it includes them. `trial_days` (Team, 3 since 2026-11-12): the free days a Checkout gives an account whose Stripe customer has never had a subscription (a card is still taken up front; the first month is charged when the trial ends unless cancelled); any later Checkout has none. Feature lines with available false are shown as coming next. The entitlement github_private is what lets genclass-dev[bot], the GitHub App, review an account's private repositories (telemetry-worker/src/github/entitlement.ts); public repositories are reviewed for everyone, whatever this file says. A self-hosted collector sets PLAN_GATES = \"open\" and gives every account the grant plan. managed_payments true would sell a plan through Stripe Managed Payments (only for fully automated digital products; telemetry-worker/README.md, Paid plans). `suggestions` (2026-11-12): what `genclass suggest` gives a plan (telemetry-worker/src/suggest.ts): `per_day`, model runs an account has a day, and `shown`, how many items of the plan it is shown (null: all); the measured checks themselves are free for everyone.",
"_about": "The one place GenClass plans are defined. telemetry-worker/src/plans.ts imports this file (limits, entitlements, Stripe lookup keys, the billing page) and genclass.dev's site reads it (the pricing page). Three plans since version 3 (2026-11-11): Free, Team and Enterprise; since version 4 (2026-11-12) a plan belongs to a project, not to an account. Free is what finds, shows and fixes the problems: the open-source runtime with every mode and its on-device model, the coding-agent loop on the developer's machine, the dashboard's problems for an account's first 3 projects (the last 7 days shown; a 4th project on Free is locked until it has a plan), and 100 problems fixed live a month per project (limits.live_fixes_per_month; past it the runtime is told to observe only until the month ends) and genclass-dev[bot] on public repositories. Team is sold per project (per_project true: one Stripe subscription of quantity 1 per project, its metadata naming the project; everyone on the account's team sees it; telemetry-worker/src/stripe.ts) and adds what a team uses: genclass-dev[bot] on private repositories, visitor analytics, forwarding, export, 90 days of history and members. Enterprise is agreed by email: a null monthly price means the plan is not sold on the site, and an account gets it from GenClass's own grant (accounts.comp_until, set by hand to the end of the agreement; accounts.comp_plan names the plan granted, grant_plan when it is empty). The classifier a person from GenClass trains is in Enterprise only. retired_plans lists the plan ids GenClass sold before (Pro and Custom until 2026-10-19, Individual until 2026-10-22): their Stripe products and prices stay GenClass's own, so a subscription to one is still cancelled with its account, opens Manage billing and is reported to the owner while it bills, but it gives no plan (it reads as Free). The worker's Stripe code and scripts/stripe-setup.mjs sell any plan given a monthly price above 0, its stripe_lookup_keys and a stripe_tax_code. Prices are US cents (per project for a per_project plan, per seat for a per_seat plan); a null yearly price means no yearly option. limits.apps null means no plan limit (the worker still caps an account at 200 apps against abuse); limits.seats is how many people a plan that is not per_seat holds (null: no limit); limits.history_days is what the dashboard shows, and data is never deleted before 90 days whatever the plan, so the longer history is there the moment an account upgrades. Ingest never depends on the plan: an app's visitor analytics are counted while its plan leaves them out, and shown once it includes them. Pro (id team; named Team until 2026-11-12) has a trial: trial_days (3) days free at Checkout, a card taken up front and charged when it ends unless cancelled, once per account (telemetry-worker/src/billing.ts trialFor). Feature lines with available false are shown as coming next. The entitlement github_private is what lets genclass-dev[bot], the GitHub App, review an account's private repositories (telemetry-worker/src/github/entitlement.ts); public repositories are reviewed for everyone, whatever this file says. A self-hosted collector sets PLAN_GATES = \"open\" and gives every account the grant plan. managed_payments true would sell a plan through Stripe Managed Payments (only for fully automated digital products; telemetry-worker/README.md, Paid plans). `suggestions` (2026-11-12): what `genclass suggest` gives a plan (telemetry-worker/src/suggest.ts): `per_day`, model runs an account has a day, and `shown`, how many items of the plan it is shown (null: all); the measured checks themselves are free for everyone. Entitlements `problems` (the problem lists, pages, activity and fix prompts on the dashboard and in the genclass command; Free shows only the totals) and `ask` (genclass ask) were added 2026-11-12 (the owner's 'limit free fully'); a plan file without the key gives them.",
"version": 4,
"currency": "usd",
"contact": "mehar@genclass.dev",
"grant_plan": "enterprise",
"retired_plans": ["pro", "custom", "individual"],
"footer": "Questions about Team, Enterprise, your own classifier, self-hosting or invoices? Email mehar@genclass.dev.",
"footer": "Questions about Pro, Enterprise, your own classifier, self-hosting or invoices? Email mehar@genclass.dev.",
"plans": [
{
"id": "free",
"name": "Free",
"summary": "Find, see and fix the problems. Up to 3 projects.",
"summary": "The totals, one suggestion, up to 3 projects.",
"price_usd_cents": { "monthly": 0, "yearly": null },
"stripe_lookup_keys": { "monthly": null, "yearly": null },
"stripe_tax_code": null,
"managed_payments": false,
"per_seat": false,
"limits": { "apps": 3, "history_days": 7, "seats": 1, "live_fixes_per_month": 100 },
"suggestions": { "per_day": 3, "shown": 3 },
"entitlements": { "dashboard": true, "forwarding": false, "export": false, "analytics": false, "custom_model": false, "github_private": false },
"suggestions": { "per_day": 3, "shown": 1 },
"entitlements": { "dashboard": true, "forwarding": false, "export": false, "analytics": false, "custom_model": false, "github_private": false, "problems": false, "ask": false },
"features": [
{ "text": "Open-source runtime, every mode", "available": true },
{ "text": "On-device model", "available": true },
{ "text": "Coding-agent loop on your machine (@genclass/mcp)", "available": true },
{ "text": "Dashboard: the problems found, last 7 days", "available": true },
{ "text": "Dashboard totals, last 7 days", "available": true },
{ "text": "Up to 3 projects", "available": true },
{ "text": "100 live fixes a month per project, then observe only", "available": true },
{ "text": "GitHub App on public repositories", "available": true },
{ "text": "Page check", "available": true },
{ "text": "Suggestions: your top 3 next steps", "available": true },
{ "text": "Suggestions: your top one", "available": true },
{ "text": "Self-host the collector", "available": true }
]
},
{
"id": "team",
"name": "Team",
"name": "Pro",
"summary": "Everything for one project, your whole team included.",
"price_usd_cents": { "monthly": 1500, "yearly": null },
"stripe_lookup_keys": { "monthly": "genclass_team_monthly", "yearly": null },
Expand All @@ -44,19 +44,24 @@
"trial_days": 3,
"limits": { "apps": null, "history_days": 90, "seats": null, "live_fixes_per_month": null },
"suggestions": { "per_day": 30, "shown": null },
"entitlements": { "dashboard": true, "forwarding": true, "export": true, "analytics": true, "custom_model": false, "github_private": true },
"entitlements": { "dashboard": true, "forwarding": true, "export": true, "analytics": true, "custom_model": false, "github_private": true, "problems": true, "ask": true },
"features": [
{ "text": "Everything in Free", "available": true },
{ "text": "3 days free to start", "available": true },
{ "text": "Every problem, its pages and a fix prompt", "available": true },
{ "text": "Ask about your app in plain words", "available": true },
{ "text": "Every suggestion, plus the model's own ideas", "available": true },
{ "text": "Website design ideas from sites like yours", "available": true },
{ "text": "Unlimited live fixes", "available": true },
{ "text": "Every suggestion, with a prompt for your agent", "available": true },
{ "text": "GitHub App on private repositories", "available": true },
{ "text": "Visitor analytics", "available": true },
{ "text": "Alerts to Sentry, PostHog, Datadog, Slack or a webhook", "available": true },
{ "text": "Data export and API", "available": true },
{ "text": "90 days of history", "available": true },
{ "text": "Your whole team on the project", "available": true }
],
"per_project": true
"per_project": true,
"trial_days": 3
},
{
"id": "enterprise",
Expand All @@ -69,9 +74,9 @@
"per_seat": false,
"limits": { "apps": null, "history_days": 365, "seats": null, "live_fixes_per_month": null },
"suggestions": { "per_day": 100, "shown": null },
"entitlements": { "dashboard": true, "forwarding": true, "export": true, "analytics": true, "custom_model": true, "github_private": true },
"entitlements": { "dashboard": true, "forwarding": true, "export": true, "analytics": true, "custom_model": true, "github_private": true, "problems": true, "ask": true },
"features": [
{ "text": "Everything in Team", "available": true },
{ "text": "Everything in Pro", "available": true },
{ "text": "Your own classifier, trained by us", "available": true },
{ "text": "Our models in our cloud", "available": true },
{ "text": "The coding-agent loop run for your team", "available": true },
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading