Set up local dev and ship a PR to Mnueron.
Two repos to know — the CLI (open source MIT) and the SaaS web app. Both run locally. We'll get them both up, point them at a personal Supabase, walk through the plugin SDK so you can extend Meet, and finish with a PR template.
Fork + clone the two repos
The CLI / MCP server lives in mnueron (MIT). The SaaS web app lives in ai-boilerplate-pro (proprietary but open by default to contributors). Fork both on GitHub, then:
git clone https://github.com/<you>/mnueron.git
git clone https://github.com/<you>/ai-boilerplate-pro.git
cd mnueron && npm install
cd ../ai-boilerplate-pro && npm installnpm install takes 2–3 minutes the first time. Node 20+ recommended.Spin up your own Supabase + apply migrations
The SaaS app needs Postgres. Use a free Supabase project so you're not racing against the prod database. Once you have the connection string, drop it in .env.local:
# ai-boilerplate-pro/.env.local
DATABASE_URL=postgresql://...supabase...
ARCHIVE_ENC_KEY=$(openssl rand -hex 32) # 32-byte hex secret for per-org credential encryption
CRON_SECRET=$(openssl rand -hex 32) # shared secret for local cron triggers
# Stripe keys are optional in dev unless you're touching billingThen push every migration to your fresh database:
npm run db:push # applies every supabase/migrations/*.sql
npm run db:status # confirms what's appliedIF NOT EXISTS guards.Run both processes side by side
The CLI and the web app are independent processes. There's a single command to start both with shared kill-on-failure behavior:
# inside ai-boilerplate-pro
npm run dev:full
# starts the CLI's MCP dashboard on :3122 and Next.js on :3000Visit http://localhost:3000 for the web app and http://localhost:3122for the CLI's local dashboard. Both hot-reload on save.
:3000 or :3122 are taken, thepredev:full hook already runs kill-port to free them. If it fails, kill the lingering processes manually or change the ports in the scripts block of package.json.Add a meeting connector (the most common contribution)
Mnueron Meet uses a MeetingSource plugin model. Granola, Fathom, Zoom, and Teams are each ~200 lines of TypeScript. To add a new one (say, Otter.ai):
- Copy
src/lib/meet/plugins/granola.tsas a template. Granola shows the polling pattern; Fathom shows the webhook pattern. - Implement the interface:
auth,list,fetch,normalize. - Register it in
src/lib/meet/registry.ts. The registry is the single seam between plugins and the rest of the pipeline. - Add an install card on
src/app/dashboard/integrations/meet/page.tsxand a docs page undersrc/app/docs/integrations/<name>.
Or extend the extractor (per-vertical templates)
Templates control how meetings turn into structured outputs. The Engineering template emits REQ-xxx / ADR-xxx / JIRA references; a Sales template emits Objections + NextSteps. Add a vertical template in:
src/lib/meet/extractors/
├── index.ts # template registry
├── prompts/ # one file per template's system prompt
└── schemas/ # one zod schema per template's output shapePattern: write a system prompt, define the output schema, add an entry to the registry, and the pipeline picks it up. The admin-only positioning page at /docs/internal/meet-vs-others lists niche templates we could ship (Legal, Healthcare, Education, IR) with the buyer + extraction targets for each.
Use Codex / Cursor as your coding partner while contributing
The same MCP setup from the developer track works while you code. Point Codex at your localMnueron (don't use a prod token in dev). Save runbooks and project conventions as memories; Codex recalls them automatically in future runs.
# Quick — store a project convention
mnueron memory save \
"PR description must include: what changed, why, screenshot if UI, test added" \
--namespace=ai-boilerplate-pro \
--tags=convention,prRun the local checks before opening a PR
Two checks the CI gate looks at. Run them locally first to avoid the round-trip:
npm run lint # eslint across the project
npx tsc --noEmit # strict typecheck — catches the silly stuff first
# For the CLI side
cd ../mnueron && npm run buildFor migration changes, do an integration check by running npm run db:push against a freshSupabase project (not the one you've been developing in). That proves the migration is idempotent end-to-end.
Open the PR
Use a focused branch name, push to your fork, and open a PR against main in the right repo. The PR template asks for:
- One sentence describing what changed.
- Why — link to the issue or describe the customer-facing impact.
- Screenshot or short video if the change is in the UI.
- The test(s) you added or ran manually.
- Migration notes if you touched
supabase/migrations/.