# Codema Full text of published articles. Drafts are omitted. Resource file bytes are not included. # 10 copy-paste AI coding prompts to ship a web app URL: https://codema.ai/articles/10-copy-paste-prompts-ship-web-app-with-ai.html Language: en Published: 2026-10-20 Description: Ten copy-paste AI coding prompts that take a web app from idea to production in Cursor, Claude Code or Codex: plan, schema, auth, tests, security, launch. Most prompting advice for coding agents comes down to one idea: **give the agent the same brief you'd give a sharp new teammate.** That means the goal, the constraints, what "done" looks like, and what to leave alone. Here are ten AI coding prompts for the full path from idea to production. They work with Cursor, Claude Code, Codex or any other agent that can read your repo and run commands. Copy them, fill in the `[brackets]`, and adjust to your stack. The examples assume Next.js and Supabase, but the structure carries over to other stacks. A tip before you start: run them in order and in **separate sessions** where it makes sense. A fresh context for each step keeps the agent focused and stops old assumptions from carrying over. ## 1. The project brief (plan before code) ```text I want to build [one-sentence product description] for [who it's for]. Before writing any code, produce a plan: 1. The core user flows (max 5), each as a numbered list of steps. 2. The data model: tables, key columns, and relationships. 3. Which pages/routes we need. 4. What we are explicitly NOT building in v1. 5. Open questions you need me to answer. Stack: [Next.js + Supabase + Vercel]. Keep v1 small enough to ship in a weekend. Do not create files yet. ``` The "do not create files yet" line matters. Planning and building are different jobs, and mixing them gets you code for a plan you never agreed to. ## 2. Write the agent's rulebook (AGENTS.md) ```text Create an AGENTS.md at the repo root for this project. Include: - Setup, dev, build, test, and lint commands (read package.json; don't invent scripts). - Code style rules you can infer from the existing code. - Folder structure: what lives where. - Security rules: never commit secrets, server-only keys never get a NEXT_PUBLIC_ prefix, every new table needs Row Level Security. - "Definition of done": build passes, tests pass, lint passes. Keep it under 80 lines. Ask me about anything you can't infer. ``` [AGENTS.md](https://agents.md/) is an open format that many coding agents read, including Codex, Cursor, GitHub Copilot's coding agent and Gemini CLI. Writing it once saves you from repeating the same rules in every chat. Our guide to [writing an AGENTS.md file](/articles/what-is-agents-md-how-to-write-one.html) covers what to put in it. ## 3. Schema with security built in ```text Using the plan we agreed on, write a SQL migration for these tables: [list tables]. Requirements: - Primary keys, foreign keys, created_at timestamps, sensible NOT NULLs. - Enable Row Level Security on every table. - Revoke default grants from anon and authenticated, then grant back only what each role needs. - One policy per operation (select / insert / update / delete), scoped with `to authenticated` and `(select auth.uid())`. - Index every column used in a policy filter. Explain each policy in one line, then show the SQL. ``` Every requirement in this prompt comes from Supabase's [Row Level Security guide](https://supabase.com/docs/guides/database/postgres/row-level-security). It warns that a table in an exposed schema without RLS "is readable and writable by any role with a grant on it", and that adding policies doesn't remove existing grants. ## 4. Auth flow ```text Add email sign-up, sign-in, and sign-out using [Supabase Auth]. - Protect every route under /app; redirect signed-out users to /login. - Use the server client for anything that reads user data. - Show clear error messages for wrong password, unconfirmed email, and network failure. - Don't build a custom password system. List the files you'll touch before you touch them. ``` ## 5. One feature, end to end ```text Implement this feature as one vertical slice: [feature]. User story: As a [user], I want to [action] so that [outcome]. Acceptance criteria: - [criterion 1] - [criterion 2] Touch only the files needed. Add or update tests for the new behavior. When done, run the build and tests and paste the results. ``` Vertical slices (UI + API + data for one feature) are much easier to review than "build the whole backend, then the whole frontend." ## 6. Tests that actually test something ```text Write tests for [file or feature]. For each function or route: - One happy-path test. - At least two edge cases (empty input, wrong user, missing record). - One test proving an unauthorized user is denied. Don't mock the thing under test. Run the tests and fix failures in the code, not by weakening assertions. Tell me if a test reveals a real bug. ``` The last two lines are there because agents sometimes make a failing test pass by loosening the assertion. Saying so up front helps prevent it. ## 7. Debug from evidence ```text Bug: [what happens] instead of [what should happen]. Steps to reproduce: [steps]. Error output: [paste the full error / stack trace / log lines] First, explain the most likely root cause and how you'd confirm it. Then add the smallest fix. Don't refactor unrelated code. Add a test that fails before the fix and passes after. ``` ## 8. Security review of the diff ```text Review the changes on this branch versus main as a security reviewer. Check specifically for: - Missing authorization checks (can user A read or change user B's data?). - Tables without Row Level Security or with overly broad policies. - Secrets in code, or server-only keys exposed to the browser (anything secret with a NEXT_PUBLIC_ prefix). - Unvalidated user input reaching SQL, HTML, redirects, or file paths. - New dependencies: does each one exist, is it maintained, is it needed? Report findings by severity with file and line. Don't change code yet. ``` This list follows the top of the [OWASP Top 10:2025](https://owasp.org/Top10/2025/): Broken Access Control is #1, followed by Security Misconfiguration and Software Supply Chain Failures. The browser-exposure check comes from how Next.js works: [`NEXT_PUBLIC_` variables are inlined into the JavaScript sent to the browser](https://nextjs.org/docs/app/guides/environment-variables). On the Supabase side, [secret keys bypass Row Level Security](https://supabase.com/docs/guides/api/api-keys) and must never ship to the client. Before launch, run through our [vibe coding security checklist](/resources/vibe-coding-security-checklist.html). ## 9. Pre-launch checklist ```text We're about to deploy to production. Produce a launch checklist for this repo and check off what you can verify yourself: - Required environment variables (names only) for Production and Preview. - Build passes with production settings. - Error pages (404, 500) exist and don't leak stack traces. - Auth redirect URLs configured for the production domain. - Database migrations applied, RLS enabled on every table. - Basic SEO: titles, meta descriptions, Open Graph image. Mark each item VERIFIED, NEEDS HUMAN, or MISSING. ``` "NEEDS HUMAN" is the important label. Some checks, like your DNS settings or your payment provider's dashboard, are outside the agent's reach, and you want it to say so instead of guessing. ## 10. Clean up before it sprawls ```text Do a cleanup pass with zero behavior changes: - Remove dead code and unused dependencies. - Consolidate duplicated helpers. - Make naming consistent with AGENTS.md. Do it as a series of small commits, each with a clear message. Run build and tests after each step and stop if anything fails. ``` ## How to get more out of these AI coding prompts - **Turn your favorites into skills.** If you paste prompt #8 every week, save it as a skill and your agent will load it when you ask for a security review. See our [guide to writing agent skills](/articles/what-are-agent-skills-write-your-first-skill.html). - **Always ask for evidence.** "Run the tests and paste the results" beats "make sure it works." - **Scope every prompt.** "Touch only the files needed" and "don't refactor unrelated code" stop runaway diffs. - **Read the diff anyway.** The prompts lower the risk, but they don't remove it. See our [checklist for reviewing AI-generated code](/articles/review-ai-written-code-before-production.html). ## Keep reading - [All ten prompts in one file: the ship-a-web-app prompt pack](/resources/ship-a-web-app-prompt-pack.html) - [How to vibe code a SaaS with Supabase and Vercel in a weekend](/articles/vibe-code-saas-supabase-vercel-weekend.html) - [How to run coding agents safely: permissions, sandboxes and secrets](/articles/run-coding-agents-safely-permissions-sandboxes.html) ## FAQ ### Do these prompts work with any coding agent? Yes. They are plain-text briefs, so they work in Cursor, Claude Code, Codex or any agent that can read your repo and run commands. The examples assume Next.js and Supabase. ### Why run each prompt in a separate session? A fresh session keeps the agent focused on one step and stops assumptions from an earlier step from carrying over into the next one. ### What makes a good prompt for a coding agent? A good prompt states the goal, the constraints, what done looks like and what to leave alone, and asks the agent to show evidence such as test output. ### Should I turn prompts into agent skills? If you paste the same prompt every week, yes. A skill loads when a task matches its description, so you stop repeating yourself. --- # How to build a bilingual app for Quebec with AI: French rules and Law 25 URL: https://codema.ai/articles/building-with-ai-in-french-quebec.html Language: en Published: 2026-10-20 Description: How to build a bilingual app for Quebec with AI: OQLF French-language rules, Law 25 privacy duties, Next.js i18n patterns and resources. > **Editor's note:** This is the English working draft of what will become our flagship French-language piece for Quebec readers. The French edition will be written for a Quebec audience, not machine-translated, and will be the primary version. Most AI building guides are written in English, for an English-speaking market. If you build a bilingual app for Quebec, you have more to think about: language rules, privacy rules, and users who expect a product that feels native in French, not translated as an afterthought. The good news is that AI coding agents make building bilingual products much easier than it used to be. This guide covers the rules to know, practical patterns for building in French with AI, and a short list of resources. *This is general information, not legal advice. Check your specific obligations with a professional or the relevant authority.* ## The rules: French language The Office québécois de la langue française (OQLF) states the basics plainly in its fact sheet for businesses ([OQLF fact sheet, PDF](https://www.oqlf.gouv.qc.ca/francisation/entreprises/memo-assistant-francisation/publications/fiche-medias-sociaux-sites-web-doc-publicitaires.pdf)): - **If your business operates in Quebec, its website must be available in French.** You can offer other languages too, but *all* of the content, product pages included, must be available in French and be of equivalent quality. - **Commercial posts, brochures, catalogues and ads** you publish on your website and social media must be written in French. Other languages are allowed as long as the content aimed at Quebec customers is always available in French. - The same fact sheet reports that **3 in 4 people in Quebec say they prefer to shop and look for information online in French.** For the software your team uses, the OQLF says employers must make the **French version of any software** available to staff, in-house applications included, and install it **in French by default** on workstations. Businesses that employ 25 or more people in Quebec for six months are subject to the francization process and must register with the OQLF ([OQLF, information technology](https://www.oqlf.gouv.qc.ca/francisation/entreprises/outils-logiciels.html), citing the Charter of the French language, arts. 4 and 141). **What this means for builders:** if you're building an internal tool or a client-facing app for a Quebec business, plan for French from day one. Retrofitting a second language into hard-coded strings is the expensive way to do it. ## The rules: privacy (Law 25) Quebec's Law 25 matters for any app that handles personal information, and AI features often do. A few provisions are especially relevant ([CAI, main changes](https://www.cai.gouv.qc.ca/protection-renseignements-personnels/sujets-et-domaines-dinteret/principaux-changements-loi-25)): - **Privacy impact assessment (EFVP)** for any project to acquire, develop or overhaul an information system involving personal information, and **before communicating personal information outside Quebec**. If your AI feature sends customer data to a service hosted elsewhere, that's worth looking at closely. - **Highest-privacy defaults.** Privacy settings for technology products offered to the public must default to the highest level of confidentiality. - **A privacy policy** in clear, simple terms, published on your website. - **Data portability**, in force since September 22, 2024: on request, you must provide a person's computerized personal information in a structured, commonly used format ([CAI](https://www.cai.gouv.qc.ca/actualites/entree-en-vigueur-dispositions-portabilite-renseignements-personnels-informatises)). We cover this in more depth in our piece on [owning your code and data](/articles/own-your-code-and-data-building-with-ai.html). ## How to build a bilingual app for Quebec with AI: patterns that work ### 1. Put the language strategy in your agent's instructions Your [`AGENTS.md`](/articles/what-is-agents-md-how-to-write-one.html) (or `CLAUDE.md`) should state the rules once, so you don't repeat them in every chat: ```markdown ## Language - The product is bilingual: French (fr-CA) and English (en). - French is a first-class language, never a fallback. Every user-facing string must exist in both dictionaries before a feature is "done". - Never hard-code user-facing text in components. Use the dictionaries in app/[lang]/dictionaries/. - Use Quebec French terminology (e.g., "courriel", not "e-mail"). When unsure of a term, flag it for human review instead of guessing. ``` ### 2. Use locale routing from the start Next.js supports internationalized routing with sub-paths like `/fr/products` or with separate domains, and its guide shows a dictionary pattern with `app/[lang]/` and one JSON file per language, loaded on the server so translations don't bloat the client bundle ([Next.js internationalization](https://nextjs.org/docs/app/guides/internationalization)). Ask your agent to set this up *before* it builds features. ### 3. Make translation part of the workflow, not a final step Agents are good at keeping two dictionaries in sync. Claude Code's docs even show translation as a CI task: `claude -p "translate new strings into French and raise a PR for review"` ([Claude Code overview](https://code.claude.com/docs/en/overview)). Note the "for review" part. A fluent French speaker should approve user-facing text, especially legal, marketing and error messages. ### 4. Package your terminology as a skill Build a small agent skill, for example `quebec-french-review`, that checks new strings against your glossary. Keep the glossary in the skill's `references/` folder so it loads only when needed ([Agent Skills spec](https://agentskills.io/specification)). Build the glossary from an authoritative source. The OQLF's [Vitrine linguistique](https://vitrinelinguistique.oqlf.gouv.qc.ca/) includes the *Grand dictionnaire terminologique* (specialized terms, definitions and translations) and the *Banque de dépannage linguistique* (grammar, spelling, syntax and writing). Our [AGENTS.md starter template](/resources/agents-md-starter-template.html) already includes a rule that every user-facing string must exist in both languages. ### 5. Search that understands French If your app has search, don't use English-only defaults. PostgreSQL, which powers Supabase, "comes with predefined configurations for many languages" and includes a French Snowball stemmer ([PostgreSQL docs](https://www.postgresql.org/docs/current/textsearch-intro.html)). That means a search for *"facturation"* can also match related word forms: ```sql select title from articles where to_tsvector('french', title || ' ' || body) @@ plainto_tsquery('french', 'facturation client'); ``` For a bilingual table, store the language for each row and use the matching configuration. ### 6. Test in French, not just in English Ask your agent for tests that render key pages in `fr` and check that no English strings slip through. Also check accents in URLs, sorting and email templates. French text often runs longer than English, so check that buttons and headings don't break your layout. ## Resources worth bookmarking - **[Vitrine linguistique (OQLF)](https://vitrinelinguistique.oqlf.gouv.qc.ca/):** terminology and writing help, including the *Grand dictionnaire terminologique*. - **[OQLF: business obligations for websites and software](https://www.oqlf.gouv.qc.ca/francisation/entreprises/outils-logiciels.html):** the official source on language obligations. - **[Commission d'accès à l'information](https://www.cai.gouv.qc.ca/protection-renseignements-personnels/sujets-et-domaines-dinteret/principaux-changements-loi-25):** Law 25 guidance for businesses. - **[Mila](https://mila.quebec/en):** the Quebec Artificial Intelligence Institute, a Montreal-based research community of more than 1,400 machine learning researchers. Worth following for research, events and training. - **[Next.js internationalization guide](https://nextjs.org/docs/app/guides/internationalization):** the routing and dictionary patterns above. ## Why this matters Quebec builders sometimes treat French as a compliance cost. We think it's an opportunity. Few AI resources are written for French-speaking builders, and a product that feels native in French stands out. That's why the French version of this guide will be our flagship piece. *À suivre.* ## Keep reading - [Own your code and data: why it matters when you build with AI](/articles/own-your-code-and-data-building-with-ai.html) - [What are agent skills? How to write your first SKILL.md](/articles/what-are-agent-skills-write-your-first-skill.html) - [What is AGENTS.md? How to write one your coding agents follow](/articles/what-is-agents-md-how-to-write-one.html) ## FAQ ### Does my website need to be in French in Quebec? Yes, if your business operates in Quebec. The OQLF says all website content, product pages included, must be available in French and be of equivalent quality. ### Can I use AI to translate my app into French? AI agents are good at keeping English and French dictionaries in sync, but a fluent French speaker should review user-facing text, especially legal, marketing and error messages. ### Does Law 25 apply to AI features? Law 25 applies to personal information, and AI features often process it. Sending customer data to a service outside Quebec calls for a privacy impact assessment first. This is general information, not legal advice. ### How do I make Postgres search work in French? Use the french text search configuration with to_tsvector and plainto_tsquery. PostgreSQL ships with a French Snowball stemmer, so related word forms match. --- # What is MCP? The Model Context Protocol explained for vibe coders URL: https://codema.ai/articles/mcp-explained-for-vibe-coders.html Language: en Published: 2026-10-20 Description: What is MCP? The Model Context Protocol lets your coding agent use real tools like your database. How it works, how to connect a server, and how to stay safe. Your coding agent is good at reading and writing files. On its own, though, it can't see your database, your error tracker or your tickets. You end up copying and pasting between tabs, and the agent works from whatever you remembered to paste. So what is MCP, and why does it fix this? The Model Context Protocol (MCP) fixes that. It's an open standard that lets an AI app connect to outside tools and data through one common interface. This guide covers what MCP is, how to connect your first server in Cursor, Claude Code or Codex, and the safety habits that matter once your agent can act on real systems. ## What is MCP? The 30-second version MCP uses a client-server setup ([MCP architecture docs](https://modelcontextprotocol.io/docs/learn/architecture)): - **The host** is the AI app you use, such as Claude Code, Cursor or VS Code. - **A client** is the connection the host opens to one server. The host creates one client per server. - **A server** is a program that gives the AI context or abilities, such as access to a filesystem, a database or a SaaS product. A server can run **locally** on your machine (using the stdio transport) or **remotely** (using the Streamable HTTP transport). Remote servers usually sign you in with OAuth. Under the hood, messages are JSON-RPC 2.0. You almost never touch that layer, because SDKs and your editor handle it. MCP has also moved to neutral governance. In December 2025, Anthropic donated it to the Agentic AI Foundation, a directed fund under the Linux Foundation. MCP became a founding project alongside Block's goose and OpenAI's AGENTS.md ([MCP blog](https://blog.modelcontextprotocol.io/posts/2025-12-09-mcp-joins-agentic-ai-foundation/), [Linux Foundation](https://www.linuxfoundation.org/press/linux-foundation-announces-the-formation-of-the-agentic-ai-foundation)). ## What a server can offer: tools, resources, prompts The protocol defines three core things a server can expose ([architecture docs](https://modelcontextprotocol.io/docs/learn/architecture)): | Primitive | What it is | Example | | --- | --- | --- | | **Tools** | Functions the AI can call to take actions | Run a SQL query, create an issue, deploy a function | | **Resources** | Data the AI can read as context | A database schema, a file, an API response | | **Prompts** | Reusable templates for interactions | A few-shot prompt for using the server's tools | Clients discover what's available with `*/list` methods, such as `tools/list`, so the set can change over time. The spec also lets servers ask *you* for input partway through a task, through a feature called **elicitation**. Supabase uses it to ask for confirmation before destructive SQL or a paid action, when your client supports it ([Supabase MCP docs](https://supabase.com/docs/guides/getting-started/mcp)). One thing to know if you build servers: the current protocol revision, `2026-07-28`, makes each request self-contained (stateless) and deprecates the older "sampling" feature ([architecture docs](https://modelcontextprotocol.io/docs/learn/architecture)). If you only use servers, your client handles this for you. ## Connect your first MCP server We'll use the hosted **Supabase MCP server** as the example, since many vibe-coded apps run on Supabase. Its URL is `https://mcp.supabase.com/mcp`. You don't need a personal access token: your client opens a browser window and you sign in ([Supabase MCP docs](https://supabase.com/docs/guides/getting-started/mcp)). **Cursor.** Add this to `.cursor/mcp.json` in your project, or to `~/.cursor/mcp.json` for all projects ([Cursor docs](https://cursor.com/docs/context/mcp)): ```json { "mcpServers": { "supabase": { "url": "https://mcp.supabase.com/mcp?project_ref=YOUR_PROJECT_REF&read_only=true" } } } ``` **Claude Code.** Use the CLI. `--scope project` writes the config to a `.mcp.json` file you can commit for your team ([Claude Code MCP docs](https://code.claude.com/docs/en/mcp)): ```bash claude mcp add --scope project --transport http supabase \ "https://mcp.supabase.com/mcp?project_ref=YOUR_PROJECT_REF&read_only=true" ``` Then run `/mcp` inside Claude Code to authenticate. **Codex.** Supabase documents this command, followed by a login step ([Supabase MCP docs](https://supabase.com/docs/guides/getting-started/mcp)): ```bash codex mcp add supabase --url "https://mcp.supabase.com/mcp?project_ref=YOUR_PROJECT_REF&read_only=true" codex mcp login supabase ``` Notice the two query parameters. `project_ref` limits the server to one project, and `read_only=true` runs every query as a read-only Postgres user. Supabase recommends both, and so do we, especially for your first week ([Supabase MCP docs](https://supabase.com/docs/guides/getting-started/mcp)). To check it worked, ask your agent: *"What tables are in my database? Use the Supabase MCP tools."* For every config format side by side, see [how to add an MCP server to Cursor, Claude Code and Codex](/articles/add-mcp-server-cursor-claude-code-codex.html), or start from our [MCP config starter files](/resources/mcp-config-starter.html). ## What it looks like day to day With a database server connected, prompts like these work without any copy-pasting: ```text List the tables in my Supabase project and show me which ones don't have Row Level Security enabled. ``` ```text Look at the orders table schema, then write a typed query helper in lib/orders.ts that matches it exactly. ``` ```text Generate TypeScript types from the current schema and update types/database.ts. ``` Supabase's server includes tools such as `list_tables`, `execute_sql`, `get_advisors` (security and performance advisors) and `generate_typescript_types` ([Supabase MCP docs](https://supabase.com/docs/guides/getting-started/mcp)). Other servers work the same way. For example, Claude Code's docs show how to connect GitHub's remote MCP server to review PRs and create issues ([Claude Code MCP docs](https://code.claude.com/docs/en/mcp)). ## Safety: the part you shouldn't skip An MCP server acts with *your* permissions. Treat connecting one like giving a new contractor a key. **1. Prompt injection is real.** Supabase's docs walk through an attack: a customer writes instructions into a support ticket, a developer asks their agent to read the ticket, and the agent follows the hidden instructions and leaks data. Claude Code's docs give a similar warning: "Servers that fetch external content can expose you to prompt injection risk" ([Supabase](https://supabase.com/docs/guides/getting-started/mcp), [Claude Code](https://code.claude.com/docs/en/mcp)). **2. Keep approvals on.** Cursor asks before using MCP tools by default, and most clients ask you to accept each tool call ([Cursor docs](https://cursor.com/docs/context/mcp), [Supabase](https://supabase.com/docs/guides/getting-started/mcp)). Read the arguments before you click approve, especially for anything that writes data. **3. Scope down.** Use read-only mode, limit the server to one project, and turn on only the tool groups you need (Supabase supports `?features=database,docs`, for example). Don't point an agent at production data unless the task really needs it ([Supabase](https://supabase.com/docs/guides/getting-started/mcp)). **4. Never hand your MCP server to customers.** Supabase is explicit about this: the server runs with your developer permissions, so use it only as an internal tool. **5. Install from sources you trust.** Cursor's guidance is to verify the source, review permissions, use restricted API keys and audit code for critical integrations ([Cursor docs](https://cursor.com/docs/context/mcp)). **6. Keep secrets out of config files.** Cursor supports `${env:NAME}` interpolation in `mcp.json`, and Claude Code supports `${VAR}` expansion in `.mcp.json`. Use them so tokens don't end up in Git. For the protocol-level risks behind these habits, read our guide to [MCP security best practices](/articles/mcp-security-best-practices.html). ## When to use MCP (and when not to) Use MCP when you keep pasting data from the same system into chat, or when you want the agent to check its work against something real, like a live schema or an error log. Skip it when a plain CLI command would do the job. And remember that every connected server adds tools the agent has to consider. Claude Code's `/doctor` checkup even flags unused MCP servers by how much context they cost ([Claude Code skills docs](https://code.claude.com/docs/en/skills)). Connect what you use, and disconnect the rest. ## Keep reading - [How to add an MCP server to Cursor, Claude Code and Codex](/articles/add-mcp-server-cursor-claude-code-codex.html) - [MCP security: how to use MCP servers without leaking data](/articles/mcp-security-best-practices.html) - [What are agent skills? How to write your first SKILL.md](/articles/what-are-agent-skills-write-your-first-skill.html) ## FAQ ### What is MCP in simple terms? MCP, the Model Context Protocol, is an open standard that lets AI apps such as Cursor, Claude Code and Codex connect to outside tools and data through one common interface. ### Is MCP safe to use? MCP is as safe as the servers you connect and the permissions you give them. Use trusted servers, keep tool approvals on, prefer read-only and project-scoped access, and keep tokens in environment variables. ### Do I need to code to use an MCP server? No. You add a server to a config file or run one command, such as claude mcp add or codex mcp add, and then sign in. Building your own server is optional. ### Who maintains MCP? Anthropic donated MCP to the Agentic AI Foundation, a directed fund under the Linux Foundation, in December 2025. --- # Own your code and data: why it matters when you build with AI URL: https://codema.ai/articles/own-your-code-and-data-building-with-ai.html Language: en Published: 2026-10-20 Description: AI makes software cheap to build, so ownership matters more. Why to own your code and data, how to avoid vendor lock-in, and a checklist to get there. Should you own your code and data when you build with AI? For most of software's history, the question barely came up, because the hard part was building it. Custom software cost so much that renting someone else's product per seat, per month, forever, was often the only sensible choice. AI coding agents have changed that. A small team, or one determined founder, can now ship in a weekend what used to take a quarter. When building gets cheap, the question that matters shifts from *"can we build it?"* to *"who owns what we built?"* Our position is simple: **if your business runs on it, you should own it.** That means the code, the database, and increasingly the AI setup that writes and maintains both. ## What "owning it" actually means Ownership is easy to claim and easy to fake. Here's a test you can run on any system your business depends on, whether you built it, bought it or had it built: 1. **The code.** Do you have the full source in a repository *you* control, with the right to change it and deploy it anywhere? 2. **The data.** Can you export everything in a standard, structured format without asking permission or paying a fee to leave? 3. **The infrastructure.** If your host disappeared tomorrow, could you deploy somewhere else in days rather than months? 4. **The know-how.** Is the way the system is built and run written down (README, `AGENTS.md`, migrations, runbooks) instead of living in one vendor's head? 5. **The economics.** Does the cost stay sensible as you grow, or does it scale with every user you add? If you answer "no" to several of these, you're renting. Renting is a fine choice when it's deliberate. It's a problem when it happened by accident. ## Why AI makes this more urgent, not less **1. AI amplifies whatever you own.** A coding agent working in your own repository can refactor, extend and fix your system on demand. An agent can't do much with a closed SaaS product beyond what its API allows. The more of your stack you own, the more an AI agent can do for you. **2. Your data is your edge.** Models are available to everyone. Your customer history, your conversions and your operational data aren't. Most worthwhile AI features, like predicting which customer will churn or which ad will perform, need that data in a place you control and can query directly. **3. Vendors change the rules.** Even good platforms change things. For example, Supabase is deprecating its legacy `anon` and `service_role` API keys by the end of 2026 in favor of new key types ([Supabase API keys](https://supabase.com/docs/guides/api/api-keys)). That's a reasonable change with a documented migration path, but it shows that every dependency comes with maintenance you don't schedule. When you own the code, you can make those changes on your own timeline. **4. Your AI setup is becoming an asset too.** Your `AGENTS.md`, your agent skills and your MCP connections hold real knowledge about how your business builds software. Keep them in open formats. Agent Skills is an open standard that works across many agents ([agentskills.io](https://agentskills.io/home)). `AGENTS.md` is read by a long list of coding tools ([agents.md](https://agents.md/)). And MCP now sits under the Linux Foundation's Agentic AI Foundation ([MCP blog](https://blog.modelcontextprotocol.io/posts/2025-12-09-mcp-joins-agentic-ai-foundation/)). If your workflow lives in these files, you can switch AI tools without starting from scratch. ## The legal angle (especially in Quebec) Ownership isn't only a strategy question. For Quebec businesses, it's increasingly a compliance one. Since **September 22, 2024**, Quebec's Law 25 has given individuals a **right to data portability**. On request, an organization must provide computerized personal information collected from that person in a structured, commonly used technological format (our translation of the French "format technologique structuré et couramment utilisé"), or send it to an organization they authorize ([Commission d'accès à l'information](https://www.cai.gouv.qc.ca/actualites/entree-en-vigueur-dispositions-portabilite-renseignements-personnels-informatises)). The CAI also says businesses must make sure that **any new project to acquire, develop or overhaul an information system** can provide personal information in such a format, and that requests follow the same 30-day deadline as other access requests ([CAI guidance](https://www.cai.gouv.qc.ca/protection-renseignements-personnels/information-entreprises-privees/responsable-protection-renseignements-personnels-entreprise)). Law 25 also requires, since September 2023, a **privacy impact assessment before personal information is communicated outside Quebec**, and privacy settings that default to the highest level of confidentiality ([CAI, main changes](https://www.cai.gouv.qc.ca/protection-renseignements-personnels/sujets-et-domaines-dinteret/principaux-changements-loi-25)). You can't meet these obligations well if you don't know where your data lives or can't export it cleanly. When you own your database, that's a query and an export. When you don't, it's a support ticket and a wait. For the French-language side of Quebec compliance, see our guide to [building a bilingual app for Quebec](/articles/building-with-ai-in-french-quebec.html). *(This is general information, not legal advice. Talk to a professional about your situation.)* ## A checklist to own your code and data You don't need to rebuild everything. Start with what matters most: - **Repository:** the source lives in a Git organization your company owns, not in a contractor's or a no-code builder's personal account. New to Git? Start with our [Git and GitHub basics for vibe coders](/articles/git-github-basics-for-vibe-coders.html). - **Database:** use a standard engine you can run anywhere. Postgres, for example, ships with `pg_dump` for exporting a database ([PostgreSQL docs](https://www.postgresql.org/docs/current/app-pgdump.html)). Check that you can actually export and restore it. Our guide to [backing up and exporting a Supabase database](/articles/back-up-supabase-database.html) walks through it. - **Accounts:** the hosting, database, domain and payment accounts are in the company's name, with at least two admins. - **Secrets:** keys live in your platform's secret storage, and you know how to rotate each one. - **Docs for humans and agents:** a README, an `AGENTS.md` and migrations in the repo. If a new developer, or a new AI agent, can't get the project running from the repo alone, you don't fully own it yet. - **Exit test:** once a year, run a "what if we had to move?" drill. Deploy a copy somewhere else. You'll learn more from that than from any contract. ## The trade-off, honestly Owning your software means taking on responsibility for it: updates, security patches, backups, monitoring. Some tools are worth renting. Email, payments and accounting are rarely where you want to be different. The line we draw is this: **rent commodities, own your core.** Your core is the system that holds your customer relationships, your operations data and the workflows that make you different. That's the part to own. ## Keep reading - [How to back up and export your Supabase database](/articles/back-up-supabase-database.html) - [What is AGENTS.md, and how to write one](/articles/what-is-agents-md-how-to-write-one.html) - [AGENTS.md starter template for Next.js and Supabase](/resources/agents-md-starter-template.html) ## FAQ ### What does it mean to own your code and data? It means the full source is in a repository your company controls, your data exports in a standard format without permission or fees, and you could redeploy elsewhere in days. ### Is renting SaaS always a mistake? No. Renting is fine when it is deliberate, for commodities such as email, payments and accounting. The risk is renting your core system by accident. ### What does Law 25 say about data portability? Since September 22, 2024, a Quebec organization must, on request, provide computerized personal information collected from a person in a structured, commonly used technological format. This is general information, not legal advice. ### How do I test whether I really own my stack? Run an exit drill once a year: deploy a copy of the system somewhere else using only the repository, the docs and a data export. --- # Cursor vs Claude Code vs Codex: how to pick an AI coding agent URL: https://codema.ai/articles/picking-a-coding-agent-cursor-claude-code-codex.html Language: en Published: 2026-10-20 Description: Cursor vs Claude Code vs Codex vs GitHub Copilot: how these AI coding agents differ in where they run, and how to choose one without lock-in. "Which AI coding agent should I use: Cursor, Claude Code or Codex?" comes up constantly, and the honest answer has changed. The leading tools have converged a lot. They read your repo, edit across files, run commands, support MCP and agent skills, and most of them read `AGENTS.md`. Choosing one is now less about raw ability and more about **where the agent runs and how it fits the way you work**. This guide compares the main options using only what their official docs say. We've left out pricing and model lists on purpose: both change often, so check each vendor's pricing page on the day you decide. ## The quick map | Tool | Where it runs | Good fit if you… | | --- | --- | --- | | **Cursor** | Its own editor, plus Cloud Agents (web, desktop, iOS, Slack, GitHub, Linear, API) and a CLI | want an AI-first editor and to hand off parallel tasks to the cloud | | **Claude Code** | Terminal, VS Code and JetBrains, a desktop app, and the web | live in the terminal or want one agent across many surfaces | | **Codex** | CLI, IDE extension, the ChatGPT desktop app, and Codex cloud | use ChatGPT already and want local + cloud in one workflow | | **GitHub Copilot** | IDEs, the Copilot CLI, and a cloud agent on GitHub.com | want work to start and end in GitHub issues and pull requests | ## Cursor Cursor describes itself as "a coding agent for building ambitious software", built around its own editor ([Cursor docs](https://cursor.com/docs)). Two things stand out: - **Cloud Agents.** These run in isolated cloud VMs with full development environments, and you can run "as many agents as you want in parallel" without your machine being online. You can start them from the desktop app, cursor.com/agents, the iOS app, Slack, GitHub or Bitbucket comments, Linear, or the API. They produce pull requests along with screenshots, videos and logs showing how the agent checked its work. Cloud Agents are billed at API pricing for the model you pick, and you'll be asked to set a spend limit ([Cloud Agents docs](https://cursor.com/docs/cloud-agent)). - **Model choice.** Cursor's docs list models from several providers (Anthropic, OpenAI, Google, its own Composer models and others), so you can switch models without switching tools ([Cursor docs](https://cursor.com/docs)). Cursor also has a CLI (`agent`) that shares its MCP configuration with the editor ([Supabase MCP docs](https://supabase.com/docs/guides/getting-started/mcp)). It loads agent skills from `.agents/skills/` and `.cursor/skills/`, and also from Claude's and Codex's skill folders ([Cursor skills docs](https://cursor.com/docs/context/skills)). ## Claude Code Anthropic's [Claude Code](https://code.claude.com/docs/en/overview) is an "agentic coding tool that reads your codebase, edits files, runs commands, and integrates with your development tools". It runs in the terminal, in VS Code and JetBrains, in a desktop app and on the web. According to the docs, "each surface connects to the same underlying Claude Code engine", so your `CLAUDE.md`, settings and MCP servers work across all of them. What it's strong at, per the docs: - **Scripting and automation.** It follows the Unix philosophy: you can pipe logs into it, run it in CI with `claude -p`, or chain it with other tools. - **Routines and parallel work.** It supports cloud and desktop scheduled tasks, subagents, and an Agent SDK for building your own agents. - **Moving between surfaces.** You can start a task on the web or your phone and pull it into your terminal, or continue a terminal session in the desktop app. - **Shared rules.** If your repo already has an `AGENTS.md`, Claude Code "can read that in place of a `CLAUDE.md`." Most surfaces require a Claude subscription or an Anthropic Console account. The terminal CLI, VS Code and JetBrains also support third-party providers ([overview](https://code.claude.com/docs/en/overview)). ## Codex OpenAI's [Codex CLI](https://developers.openai.com/codex/cli) works on your local repo from the terminal. It has a `/review` command for checking changes before you commit, `codex exec` for scripts and CI, `codex cloud` to send work to a cloud environment, and `codex mcp` to connect tools. `/init` creates an `AGENTS.md` for the project. Skills are available in the ChatGPT desktop app, the Codex CLI and the IDE extension, and skills packaged as plugins also work in ChatGPT on the web and mobile ([Codex skills docs](https://developers.openai.com/codex/skills)). You sign in with your ChatGPT account or another available method on first run. That makes Codex the natural choice if your team already works inside ChatGPT ([Codex CLI](https://developers.openai.com/codex/cli)). ## GitHub Copilot Copilot's [cloud agent on GitHub.com](https://docs.github.com/en/copilot/concepts/agents/coding-agent/about-coding-agent) can research a repo, plan changes and implement them in an ephemeral cloud environment. It handles branches, commits and pull requests for you. GitHub documents some clear limits that are worth knowing before you plan around it: - It works on **one repository per task**, one branch at a time, and opens **one pull request per task**. - Each session has a **maximum run time of 59 minutes**. - It only works with repositories hosted on GitHub. If your whole process already lives in GitHub issues and PR reviews, those limits may not matter, and the integration is hard to beat. ## And the others The [AGENTS.md](https://agents.md/) site lists more than 20 tools that read the format, including Gemini CLI, Jules, Windsurf, Devin, Zed, Aider, opencode, Warp, Junie and goose. Many of these are good choices too, especially if you want open-source tools or a particular editor. ## How to choose an AI coding agent: five questions 1. **Where do you spend your day?** In an editor, choose an editor-first tool (Cursor, or Copilot/Claude Code/Codex inside VS Code or JetBrains). In a terminal, Claude Code and the Codex CLI feel natural. 2. **Do you want to delegate work in parallel?** All four offer some form of cloud or background agent. Compare how each one sets up the environment (dependencies, secrets, network access), because that decides whether the agent can actually test its work. 3. **Where does your work start and end?** If it's GitHub issues and PRs, Copilot's cloud agent fits. Cursor's Cloud Agents can be started from Slack, Linear and GitHub, and Claude Code can turn a Slack mention into a pull request. 4. **How much does model choice matter to you?** Cursor's model menu covers several providers. Claude Code and Codex are built around their own companies' models. 5. **What does it cost at *your* usage?** Run a real task from your own backlog in each tool you're considering, then check the bill or usage dashboard. Benchmarks won't tell you this. ## Don't marry a tool: keep your setup portable The good news is that switching is cheaper than it used to be, because the setup that matters now uses shared standards: - **`AGENTS.md`** for project rules ([how to write one](/articles/what-is-agents-md-how-to-write-one.html)). Codex, Cursor, Copilot's coding agent and many others read it, and Claude Code can use it in place of `CLAUDE.md`. - **Agent skills** (`SKILL.md` folders) for repeatable procedures ([how to write your first skill](/articles/what-are-agent-skills-write-your-first-skill.html)). They're supported by Claude Code, Cursor and Codex, and Cursor even loads the other tools' skill folders. - **MCP servers** for tools and data ([how to add one to each tool](/articles/add-mcp-server-cursor-claude-code-codex.html)). All four tools support MCP. If you put your effort into these three instead of tool-specific features, you can try a new agent in an afternoon. Many teams end up using two: one in the editor for interactive work, and one in the cloud for background tasks. ## Keep reading - [How to run coding agents safely: permissions, sandboxes and secrets](/articles/run-coding-agents-safely-permissions-sandboxes.html) - [AGENTS.md starter template for Next.js and Supabase](/resources/agents-md-starter-template.html) - [10 copy-paste AI coding prompts to ship a web app](/articles/10-copy-paste-prompts-ship-web-app-with-ai.html) ## FAQ ### Which is the best AI coding agent? There is no single best AI coding agent. Pick the one that runs where you work: Cursor for an AI-first editor, Claude Code or Codex for the terminal, and Copilot if your work lives in GitHub. ### Can I use more than one coding agent on the same repo? Yes. Most of them read AGENTS.md, support agent skills and connect to MCP servers, so one repository setup can serve several tools. ### Does Claude Code read AGENTS.md? Yes. Recent Claude Code versions read AGENTS.md when the project has no CLAUDE.md, and you can also import it from CLAUDE.md with an @AGENTS.md line. ### How do I compare the cost of coding agents? Run a real task from your own backlog in each tool you are considering and check its usage dashboard. Pricing changes often, so check each vendor pricing page on the day you decide. --- # Predictive creative testing: how to test AI ad creatives before you spend URL: https://codema.ai/articles/predictive-creative-testing-ai-ad-creatives.html Language: en Published: 2026-10-20 Description: Predictive creative testing uses AI to generate and pre-score ad creatives, then confirms the winners with real Google Ads or Meta experiments. Classic creative testing works like this: make a handful of ads, split the budget, wait, and keep the winner. It works, but it's slow and expensive, and you can only test as many ideas as your budget allows. Most of the ideas you *didn't* test never get a chance. Predictive creative testing adds a step at the front. **AI helps you generate many variations and score them before any money is spent**, and then real experiments confirm which of the shortlisted ones actually win. This guide explains the workflow, what prediction can and can't do, and how to set up the confirmation step properly. ## How predictive creative testing works: predict, then prove Think of it as a funnel: 1. **Generate** a wide set of creative variations (hooks, headlines, visuals, video openings, calls to action). 2. **Predict:** score each variation with a model before launch, and drop the obvious losers. 3. **Prove:** run a controlled live test on the shortlist only. 4. **Learn:** feed the real results back into how you generate and score the next round. Prediction doesn't replace testing. It decides **what's worth testing**. Paid experiments are your most expensive source of truth, so you want to spend them on the strongest candidates, not on variation #37 of a headline nobody liked. ## Step 1: generate variations with structure "Make me 50 ads" gives you 50 versions of the same idea. Generate along clear dimensions instead, so the results are comparable and you can learn from them: ```text Product: [one-line description] Audience: [who, what they care about, what they're skeptical of] Offer: [the offer and the single action we want] Generate ad concepts as a table. Vary ONE dimension at a time: - 5 hooks (first line / first 2 seconds of video), same body and CTA - 5 value angles (save time / save money / status / safety / ease) - 3 CTAs, same hook and angle For each: the copy, a one-line visual direction, and which audience objection it addresses. No claims we can't prove. ``` The last line matters. Generated ad copy invents statistics and guarantees easily, so treat every claim in it as unverified until you've checked it. ## Step 2: score before you spend This is the "predictive" part. In practice, teams do it in a few ways, from simplest to most involved: - **A structured checklist** applied the same way to every concept: is the hook clear in the first two seconds, is there a single message, does it fit the platform's format, does it address a real objection. An LLM can apply a written rubric consistently across hundreds of variations, but the rubric has to come from you. - **Your own history.** If you have past campaign results, a model can learn which attributes (hook type, length, format, angle) came with better results *for your audience*. This is where prediction is most useful, because it's grounded in your data rather than someone else's averages. - **Specialized prediction tools** that score creatives, including videos, for likely engagement before launch. Whichever you use, keep two rules: 1. **A score is a prior, not a result.** It tells you where to put your test budget, not which ad won. 2. **Track how good the predictions are.** After each live test, compare the predicted ranking with the real one. If the model keeps getting it wrong for your audience, give its scores less weight. ## Step 3: confirm with a real experiment The shortlist goes into a proper controlled test. The ad platforms have built-in tools for this. Meta offers A/B testing for ads ([Meta Business Help Center](https://www.facebook.com/business/help/1738164643098669)), and Google Ads offers experiments that compare a control against a treatment. Google's documentation includes several details that are easy to get wrong: - **A split controls eligibility, not delivery.** A 50/50 traffic split means both arms enter the same number of eligible auctions. It does *not* guarantee equal impressions or spend, which still depend on auction dynamics like Ad Rank and bidding ([Google Ads Help](https://support.google.com/google-ads/answer/10683687?hl=en)). - **You can't change the split mid-test.** If you want a different split, you have to create a new experiment ([Experiments FAQs](https://support.google.com/google-ads/answer/13826584?hl=en)). - **Give it time to settle.** Google suggests allowing 7–14 days for the treatment arm to stabilize, and avoiding changes during a bid strategy's learning phase, which typically lasts about 7 days ([Google Ads Help](https://support.google.com/google-ads/answer/10683687?hl=en)). - **Volume decides how much you can trust the result.** Google's "Experiment Power" guidance says power depends on campaign volume, how much performance varies, the traffic split and the test's duration. A 50/50 split gets you results faster ([Google Ads Help](https://support.google.com/google-ads/answer/15911255?hl=en)). - **Sanity-check your setup.** Google describes running an A/A test (two identical arms) as a way to confirm there are no statistically significant differences in clicks, impressions, CTR or CPC when nothing differs ([Google Ads Help](https://support.google.com/google-ads/answer/9232676?hl=en)). The practical consequence: **test fewer variations, properly.** Two or three well-chosen candidates with enough budget will teach you more than ten that each get too little traffic to reach a conclusion. This is exactly why the prediction step pays for itself. ## Step 4: close the loop After each test, record: - each variation's attributes (hook type, angle, format, length, CTA), - its predicted score and its actual result, - the audience and platform it ran on. Over time, that table becomes your most valuable marketing asset. Your next round of generation can start from what actually worked, and your scoring can be tuned to your own customers. Without this loop, you're running the same experiment over and over. Tag every variation with consistent UTM parameters so the results line up in analytics. Our [UTM tracking setup guide](/articles/utm-tracking-setup-guide.html) has a naming scheme you can copy. ## Common mistakes - **Testing too many things at once.** If the hook, visual and CTA all change together, you won't know which one made the difference. - **Ending tests early** because one arm looks ahead after two days. - **Trusting the score more than the result.** When the model and the market disagree, the market wins. - **Letting AI invent claims.** Every number and promise in an ad needs a source you can stand behind. - **Forgetting the landing page.** A great ad pointing to a slow or confusing page will lose to an average ad pointing to a clear one. ## Keep reading - [GA4 predictive audiences: how to use them in Google Ads](/articles/ga4-predictive-audiences-google-ads.html) - [UTM tracking setup: a naming guide for AI-built sites](/articles/utm-tracking-setup-guide.html) - [Own your code and data: why it matters when you build with AI](/articles/own-your-code-and-data-building-with-ai.html) ## FAQ ### What is predictive creative testing? Predictive creative testing is a workflow where AI helps generate and pre-score ad creatives before launch, and controlled live experiments then confirm which shortlisted variations actually win. ### Can AI predict which ad will perform best? AI can rank variations and help you decide what is worth testing, especially when it learns from your own campaign history, but only a live experiment tells you which ad won. ### How long should a Google Ads experiment run? Google suggests allowing 7 to 14 days for the treatment arm to stabilize, and avoiding changes during a bid strategy learning phase, which typically lasts about 7 days. ### How many ad variations should I test at once? Test fewer variations, properly. Two or three strong candidates with enough budget teach you more than ten that each get too little traffic. --- # How to review AI-generated code before production: a checklist URL: https://codema.ai/articles/review-ai-written-code-before-production.html Language: en Published: 2026-10-20 Description: A practical routine to review AI-generated code before production: access control first, then secrets, dependencies, errors, and agents reviewing agents. AI agents write code fast, and that's exactly why you need to review AI-generated code more carefully now. Generated code is usually clean, well named and confident, which makes it easy to approve without really reading it. GitHub's own documentation for its coding agent says plainly that agents "can produce incorrect or suboptimal code, including code that contains security vulnerabilities," and that session logs "do not replace your own review and testing" ([GitHub Docs](https://docs.github.com/en/copilot/concepts/agents/coding-agent/about-coding-agent)). You don't need to be a senior engineer to review well. You need a routine that puts the riskiest things first. Here's ours. ## Step 0: make the diff reviewable Most bad reviews start with a diff that's too big to review. Before you read any code: - **Ask for small changes.** One feature or one fix per branch. If the agent touched 40 files for a button, ask it to split the work into smaller pull requests. Cursor even has a built-in `/split-to-prs` skill for this ([Cursor docs](https://cursor.com/docs/context/skills)). - **Ask for a summary of intent.** "List every file you changed and why, in one line each." Then compare the list with what you asked for. Changes you didn't request are your first red flag. - **Ask for evidence.** The build output, the test results and the lint results, pasted into the conversation, not just "tests pass." ## Step 1: access control first Broken Access Control is #1 on the [OWASP Top 10:2025](https://owasp.org/Top10/2025/). OWASP reports that "100% of the applications tested were found to have some form of broken access control" ([A01:2025](https://owasp.org/Top10/2025/A01_2025-Broken_Access_Control/)). For most vibe-coded apps, this is the bug that matters most. For every new route, server action or query, ask one question: **can user A read or change user B's data?** If you're on Supabase, check the database layer as well: - **Every table in an exposed schema has RLS enabled.** Supabase warns that a table without it "is readable and writable by any role with a grant on it," and that adding policies doesn't revoke existing grants ([Supabase RLS](https://supabase.com/docs/guides/database/postgres/row-level-security)). - **Policies name a role** (`to authenticated`) and use `(select auth.uid())`. - **Update policies have `with check`.** Without it, a user may be able to reassign a row to someone else. - **Watch out for views.** By default, views bypass RLS. On Postgres 15 and above, create them `with (security_invoker = true)`. - **Don't base policies on `user_metadata`.** Users can edit it themselves. The fastest way to verify is to make the agent prove it. Ask it to write a test where a second user tries to read, update and delete the first user's records, and to show that the test fails before the fix and passes after. Our [Supabase RLS audit skill](/resources/supabase-rls-audit-skill.html) gives your agent a checklist for the database side. ## Step 2: secrets and the browser boundary AI-written code often blurs the line between server and client. Check these: - **No `NEXT_PUBLIC_` on anything secret.** Next.js inlines these values into the JavaScript bundle sent to the browser at build time ([Next.js docs](https://nextjs.org/docs/app/guides/environment-variables)). - **No Supabase secret key (or legacy `service_role` key) in client code.** It "bypasses every Row Level Security policy you have" ([Supabase API keys](https://supabase.com/docs/guides/api/api-keys)). The publishable key is the only one meant for the browser. - **No hardcoded credentials, even in tests or seed scripts.** Search the diff for `key`, `secret`, `token`, `password` and `Bearer`. - **Turn on secret scanning.** GitHub runs it automatically and for free on public repositories. For organization-owned private repos, it's available with GitHub Secret Protection on GitHub Team or Enterprise Cloud. If something does leak, **rotate the credential right away.** GitHub notes that removing it from Git history is "time-intensive and often unnecessary if you've already revoked the credential" ([GitHub secret scanning](https://docs.github.com/en/code-security/secret-scanning/introduction/about-secret-scanning)). ## Step 3: every new dependency Software Supply Chain Failures sits at #3 in the OWASP 2025 list. It expands 2021's "Vulnerable and Outdated Components" to cover the whole dependency and build ecosystem ([OWASP](https://owasp.org/Top10/2025/)). AI adds a twist: **package hallucinations**, where the model recommends a package that doesn't exist. Attackers can register those names and publish malicious code under them. In a peer-reviewed study presented at USENIX Security 2025, researchers generated 576,000 code samples with 16 LLMs. They found an average hallucinated-package rate of at least 5.2% for commercial models and 21.7% for open-source models, with 205,474 unique made-up package names ([Spracklen et al., USENIX Security 2025](https://www.usenix.org/conference/usenixsecurity25/presentation/spracklen)). So for every line added to `package.json` or `requirements.txt`: - Does the package exist on the official registry, and is it the one you meant (check for near-miss spellings)? - Is it maintained, and is it widely used? - Do you actually need it, or would a few lines of code do the job? ## Step 4: input, output and errors - **User input** that reaches SQL, HTML, redirects, file paths or shell commands should be validated or parameterized. Injection is still on the OWASP list, at #5. - **Error handling.** "Mishandling of Exceptional Conditions" is new at #10 ([OWASP](https://owasp.org/Top10/2025/)). Look for empty `catch` blocks, errors that are swallowed and then reported as success, and stack traces shown to users. - **Logging.** Make sure failures are logged somewhere you'll actually see them, and that the logs contain no secrets or personal data. ## Step 5: does it do what you asked? Security review isn't the whole job. Read the code against your acceptance criteria: - Does it handle empty states, missing records and slow networks? - Did the agent "fix" a failing test by weakening the assertion? - Did it add a TODO, a stub or a mock in production code to get things working? - Is there a simpler version? AI code tends to over-abstract. ## Use agents to review agents (but not instead of you) The major tools ship review features you can run before your own pass: - **Claude Code** has a bundled `/code-review` skill ([Claude Code docs](https://code.claude.com/docs/en/skills)). - **Cursor** has built-in `/review`, `/review-bugbot` and `/review-security` skills ([Cursor docs](https://cursor.com/docs/context/skills)). - **Codex CLI** has `/review`, which reports prioritized findings "without modifying your working tree" ([Codex CLI](https://developers.openai.com/codex/cli)). - **GitHub Copilot** code review can review pull requests and suggest fixes ([GitHub Docs](https://docs.github.com/en/copilot/concepts/agents/coding-agent/about-coding-agent)). Two habits make AI review more useful. First, run it in a **fresh session**, or with a different tool or model than the one that wrote the code, so the reviewer doesn't share the author's assumptions. Second, give it a **specific checklist** (Steps 1–4 above) instead of "review this." Treat AI findings as leads, not verdicts. Confirm each one, and remember that "no issues found" doesn't mean the code is safe. ## How to review AI-generated code: the one-screen checklist ```text [ ] Diff is small and every changed file is expected [ ] Build, tests, lint pass (output pasted, not claimed) [ ] User A cannot read/change user B's data (tested) [ ] RLS on every exposed table; update policies have WITH CHECK [ ] No secrets in code; nothing secret has a NEXT_PUBLIC_ prefix [ ] Every new dependency exists, is intended, and is needed [ ] Input validated/parameterized; errors not swallowed [ ] Acceptance criteria met; no weakened tests or leftover stubs [ ] AI review run in a fresh session; findings verified by a human ``` Save it as an agent skill and you can run it on every branch. Our [code review skill](/resources/code-review-skill.html) does exactly that, and our [vibe coding security checklist](/resources/vibe-coding-security-checklist.html) turns Steps 1 to 4 into a 30-minute pre-launch pass. ## Keep reading - [How to run coding agents safely: permissions, sandboxes and secrets](/articles/run-coding-agents-safely-permissions-sandboxes.html) - [How to vibe code a SaaS with Supabase and Vercel in a weekend](/articles/vibe-code-saas-supabase-vercel-weekend.html) - [Git and GitHub basics for vibe coders](/articles/git-github-basics-for-vibe-coders.html) ## FAQ ### Is AI-generated code safe to deploy without review? No. GitHub documentation says coding agents can produce code that contains security vulnerabilities and that session logs do not replace your own review and testing. ### What should I check first in AI-written code? Check access control first. Ask whether user A can read or change user B data, and on Supabase confirm every exposed table has Row Level Security enabled. ### What is a hallucinated package? A hallucinated package is a dependency an AI model recommends that does not exist. Attackers can register those names, so confirm every new package on the official registry. ### Can an AI agent review its own code? It can help, but run the review in a fresh session or with a different tool, give it a specific checklist, and treat its findings as leads that a human confirms. --- # How to vibe code a SaaS with Supabase and Vercel in a weekend URL: https://codema.ai/articles/vibe-code-saas-supabase-vercel-weekend.html Language: en Published: 2026-10-20 Description: A two-day plan to vibe code a SaaS with an AI agent, Next.js, Supabase and Vercel, including the Row Level Security steps most weekend builds skip. If you want to vibe code a SaaS, getting a working version online in a weekend is realistic now. The hard part isn't writing the code: your agent will write plenty. It's ending Sunday with something that's **secure, deployed and still understandable on Monday**. This is the two-day plan we'd follow with an AI coding agent (Cursor, Claude Code, Codex or similar), Next.js, Supabase for the database and auth, and Vercel for hosting. The example is a simple "client portal" where users sign in and manage their own records, but the steps fit most CRUD-style SaaS ideas. ## Before you vibe code a SaaS: decide what you're *not* building Write one paragraph: who it's for, the single job it does, and the 3–5 screens it needs. Then make a "not in v1" list (teams, roles, billing tiers, admin dashboards, mobile app). Paste both into your agent and ask for a plan before it writes any code. Our [prompt starter pack](/articles/10-copy-paste-prompts-ship-web-app-with-ai.html) has a template for this. ## Saturday morning: project scaffolding **1. Create a Supabase project** from the Supabase Dashboard ([Supabase Next.js quickstart](https://supabase.com/docs/guides/getting-started/quickstarts/nextjs)). **2. Scaffold the app** with the official template. It comes with cookie-based auth, TypeScript and Tailwind CSS already set up: ```bash npx create-next-app@latest my-app -e with-supabase ``` The template installs `@supabase/supabase-js` and `@supabase/ssr`, and creates a browser client in `lib/supabase/client.ts` and a server client in `lib/supabase/server.ts` ([quickstart](https://supabase.com/docs/guides/getting-started/quickstarts/nextjs)). **3. Add your environment variables.** Rename `.env.example` to `.env.local` and fill in the two values from your project's Connect panel: ```bash NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=sb_publishable_... ``` The publishable key is designed to be public. It only reaches what your Row Level Security policies allow. Supabase is deprecating the older `anon` and `service_role` keys by the end of 2026, so if a tutorial (or your AI) tells you to paste a long key that starts with `eyJ`, it was written for the legacy keys ([Supabase API keys](https://supabase.com/docs/guides/api/api-keys)). **4. Give your agent context** (optional, but worth it). Supabase publishes agent skills (`npx skills add supabase/agent-skills`) and a hosted MCP server, so your agent works from current Supabase patterns instead of whatever it remembers from training ([quickstart](https://supabase.com/docs/guides/getting-started/quickstarts/nextjs)). If you connect the MCP server, scope it to this one project, and use `read_only=true` while you're exploring ([Supabase MCP](https://supabase.com/docs/guides/getting-started/mcp)). ## Saturday afternoon: Supabase data model and Row Level Security This is the step most weekend builds get wrong, so do it before any UI. Ask your agent for a migration, and make it follow Supabase's [RLS procedure](https://supabase.com/docs/guides/database/postgres/row-level-security): enable RLS, revoke the default grants, grant back only what each role needs, and write one policy per operation. For a table where each user owns their rows, it looks like this: ```sql create table public.projects ( id uuid primary key default gen_random_uuid(), user_id uuid not null references auth.users (id), name text not null, created_at timestamptz not null default now() ); alter table public.projects enable row level security; revoke all on table public.projects from anon, authenticated; grant select, insert, update, delete on table public.projects to authenticated; create policy "owners read projects" on public.projects for select to authenticated using ((select auth.uid()) = user_id); create policy "owners create projects" on public.projects for insert to authenticated with check ((select auth.uid()) = user_id); create policy "owners update projects" on public.projects for update to authenticated using ((select auth.uid()) = user_id) with check ((select auth.uid()) = user_id); create policy "owners delete projects" on public.projects for delete to authenticated using ((select auth.uid()) = user_id); create index projects_user_id_idx on public.projects using btree (user_id); ``` Why each piece is there, according to Supabase's docs: - **A table in an exposed schema without RLS is readable and writable by any role with a grant on it.** Policies alone don't take existing grants back. - **`with check` on update** stops a user from reassigning a row to someone else. - **Wrapping `auth.uid()` in `select`** lets Postgres cache the result per statement instead of calling it for every row. - **Indexing `user_id`** keeps the policy fast as the table grows. Then **test it**. Supabase recommends a pgTAP test file per table under `supabase/tests/`, run with `supabase test db`, that checks both what's allowed and what's denied for `anon` and `authenticated`. In their words: "Until the suite passes, you don't know whether the policies do what you intended." Ask your agent to write these tests from the policies, and include a "user B can't see user A's rows" case. Our [Supabase RLS audit skill](/resources/supabase-rls-audit-skill.html) packages these checks for your agent. ## Saturday evening: auth and the first feature The template already has sign-up and sign-in. Your job is to: 1. Decide which routes are public. The template redirects signed-out visitors to the sign-in page for most routes, and the quickstart shows how to add exceptions in `lib/supabase/proxy.ts` ([quickstart](https://supabase.com/docs/guides/getting-started/quickstarts/nextjs)). 2. Build **one** feature as a vertical slice: list, create, edit and delete for your main table, using the server client. 3. Run the build and tests before you stop for the night. ## Sunday morning: deploy to Vercel **1. Push to GitHub and import the repo into Vercel.** The first deployment of a new project is always a production deployment. After that, pushes to `main` deploy to production, and other branches and pull requests get preview deployments with their own URLs ([Vercel environments](https://vercel.com/docs/deployments/environments)). **2. Connect Supabase.** The [Supabase integration on the Vercel Marketplace](https://vercel.com/marketplace/supabase) can sync your Supabase environment variables to your Vercel project automatically, including `NEXT_PUBLIC_SUPABASE_URL` and `NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY`. It also adds server-side variables such as `SUPABASE_SECRET_KEY` and Postgres connection strings, so treat the whole set with care. You can also add variables by hand in project settings. Either way, remember that environment variable changes apply to *new* deployments only ([Vercel env vars](https://vercel.com/docs/environment-variables)). **3. Mind the `NEXT_PUBLIC_` rule.** Next.js inlines any `NEXT_PUBLIC_` variable into the JavaScript sent to the browser at build time ([Next.js docs](https://nextjs.org/docs/app/guides/environment-variables)). The publishable key belongs there. The secret key, which bypasses RLS, must never get that prefix ([Supabase API keys](https://supabase.com/docs/guides/api/api-keys)). **4. Set auth redirect URLs** in Supabase for your production domain, so sign-up confirmation emails point to the live site. Ask your agent to list every URL the auth flow uses. ## Sunday afternoon: billing (optional) and polish If you're charging from day one, [Stripe Checkout](https://docs.stripe.com/payments/checkout) gives you a prebuilt payment page for one-time and subscription payments, so you don't have to build card forms yourself. Keep the Stripe secret key server-side, just like the Supabase one. Then polish what matters: empty states, error messages, a 404 page and a landing page that says what the product does in one sentence. ## Sunday evening: the launch checklist Before you share the link, go through this list: - [ ] Every table has RLS enabled, and the pgTAP tests pass. - [ ] No secret has a `NEXT_PUBLIC_` prefix, and none is committed to Git. - [ ] Production and Preview have the environment variables they need. - [ ] Auth redirect URLs match the production domain. - [ ] The build passes on Vercel, and you've clicked through the main flow on the live URL. - [ ] You've read the full diff at least once. See our [checklist for reviewing AI-generated code](/articles/review-ai-written-code-before-production.html). Supabase's own [production notes](https://supabase.com/docs/guides/getting-started/quickstarts/nextjs) say the same thing: review your RLS policies, keep credentials in environment variables rather than source control, and set up a custom domain when you go live. ## What the weekend version won't cover A weekend build is a v1. Roles and teams, audit logs, [backups you've actually tested](/articles/back-up-supabase-database.html), rate limiting and proper monitoring come next. Plan for them before real customers depend on the product. ## Keep reading - [Git and GitHub basics for vibe coders](/articles/git-github-basics-for-vibe-coders.html) - [How to back up and export your Supabase database](/articles/back-up-supabase-database.html) - [Pre-deploy check skill for coding agents](/resources/pre-deploy-check-skill.html) ## FAQ ### Can you really build a SaaS in a weekend with AI? You can ship a small, secure v1 in a weekend if you keep the scope tight. Roles, audit logs, tested backups, rate limiting and monitoring usually come after. ### Which Supabase key is safe to use in the browser? Only the publishable key. It reaches only what your Row Level Security policies allow. The secret key bypasses RLS and must never get a NEXT_PUBLIC_ prefix. ### How do I test Supabase Row Level Security? Supabase recommends a pgTAP test file per table under supabase/tests/, run with supabase test db, that checks what anon and authenticated users can and cannot do. ### Does Vercel deploy every branch? After the first deployment, pushes to main deploy to production, and other branches and pull requests get preview deployments with their own URLs. --- # What are agent skills? How to write your first SKILL.md URL: https://codema.ai/articles/what-are-agent-skills-write-your-first-skill.html Language: en Published: 2026-10-20 Description: Agent skills are SKILL.md folders your AI agent loads on demand. Learn the format and write your first skill for Claude Code, Cursor and Codex. If you keep pasting the same instructions into your coding agent ("run the tests first", "use our API error format", "never touch the migrations folder"), an agent skill is probably what you need. Agent skills are a simple, open format for giving an AI agent a reusable procedure. You write it once, put it in a folder, and the agent loads it when a task calls for it. This guide covers what a skill is, how agents use one, and how to write your first, with a copy-paste example at the end. ## What agent skills are According to the [Agent Skills overview](https://agentskills.io/home), a skill is "a folder containing a `SKILL.md` file". That file holds some metadata (at minimum a `name` and a `description`) plus instructions that tell the agent how to do a specific task. A skill can also bundle scripts, reference docs, templates and other files. The format was originally developed by Anthropic and released as an open standard, and it has since been adopted by a growing number of agent products ([agentskills.io](https://agentskills.io/home)). In practice that means one skill folder can work across several tools: - **Claude Code** says its skills "follow the Agent Skills open standard", and it adds its own optional extras on top ([Claude Code docs](https://code.claude.com/docs/en/skills)). - **Cursor** describes Agent Skills as "an open standard" and loads skills from `.agents/skills/` and `.cursor/skills/` in your project. For compatibility it also reads `.claude/skills/` and `.codex/skills/` ([Cursor docs](https://cursor.com/docs/context/skills)). - **Codex** says its skills "build on the open agent skills standard" and scans `.agents/skills` from your working directory up to the repo root ([Codex docs](https://developers.openai.com/codex/skills)). So if you put a skill in `.agents/skills/` in your repo, Cursor and Codex both look there. Claude Code uses `.claude/skills/`. Check each tool's docs for the exact paths you need. ## How agents use skills: progressive disclosure Skills are cheap to keep around because agents don't load them all at once. The spec describes three stages ([agentskills.io](https://agentskills.io/home)): 1. **Discovery.** At startup the agent loads only each skill's `name` and `description`, which is just enough to know when a skill might be relevant. 2. **Activation.** When a task matches a skill's description, the agent reads the full `SKILL.md`. 3. **Execution.** The agent follows the instructions, running bundled scripts or reading referenced files only if it needs them. There's a practical lesson in this: **the description does most of the work.** If it's vague, the agent won't know when to use the skill. Codex's docs recommend front-loading "the key use case and trigger words" so a host can still match the skill when descriptions get shortened ([Codex docs](https://developers.openai.com/codex/skills)). You can also call a skill directly. Claude Code and Cursor let you type `/skill-name`. In the Codex CLI or IDE extension, you type `$` to mention a skill or run `/skills` ([Claude Code](https://code.claude.com/docs/en/skills), [Cursor](https://cursor.com/docs/context/skills), [Codex](https://developers.openai.com/codex/skills)). ## The SKILL.md format Here's the structure from the [specification](https://agentskills.io/specification): ```text my-skill/ ├── SKILL.md # Required: metadata + instructions ├── scripts/ # Optional: executable code ├── references/ # Optional: documentation ├── assets/ # Optional: templates, resources └── ... ``` `SKILL.md` starts with YAML front matter, then Markdown instructions. The spec defines these front matter fields: | Field | Required | Notes | | --- | --- | --- | | `name` | Yes | Up to 64 characters. Lowercase letters, numbers and hyphens only. No leading, trailing or double hyphens. Must match the folder name. | | `description` | Yes | Up to 1,024 characters. Say what the skill does *and* when to use it. | | `license` | No | A license name or a bundled license file. | | `compatibility` | No | Environment requirements, up to 500 characters. Most skills don't need it. | | `metadata` | No | Free-form key-value pairs. | | `allowed-tools` | No | Pre-approved tools. Marked experimental, and support varies by agent. | Two other guidelines from the spec are worth following: keep the main `SKILL.md` under 500 lines, and move detailed reference material into separate files that the agent reads only when needed. Individual tools add their own optional fields. For example, Claude Code and Cursor both support `disable-model-invocation: true`, which stops the agent from triggering a skill automatically, so it runs only when you call it ([Claude Code](https://code.claude.com/docs/en/skills), [Cursor](https://cursor.com/docs/context/skills)). If you want a skill to stay portable, stick to the spec fields. Claude Code's docs warn that uploading to claude.ai or the Skills API fails with a hard error when the front matter contains fields outside the spec. ## How to write your first skill: a pre-deploy check A good first skill is a procedure you already repeat by hand. For most vibe coders, that's "is this safe to ship?" Here's a portable skill that runs a short pre-deploy checklist. Create the folder (use `.agents/skills/` for Cursor and Codex, or `.claude/skills/` for Claude Code): ```bash mkdir -p .agents/skills/pre-deploy-check ``` Then save this as `.agents/skills/pre-deploy-check/SKILL.md`: ```markdown --- name: pre-deploy-check description: Runs a pre-deploy checklist on the current branch (build, tests, lint, secrets, env vars, database security) and reports blockers. Use when the user asks if something is ready to ship, deploy, merge, or go to production. --- # Pre-deploy check Run these steps in order. Do not fix anything unless the user asks; report first. ## 1. Build and tests - Run the project's build, test, and lint commands (check package.json scripts or AGENTS.md). - Record each command and whether it passed. ## 2. Secrets - Search the diff against the main branch for hardcoded keys, tokens, passwords, or connection strings. - Flag any secret-looking value that is not read from an environment variable. - Flag any server-only secret referenced with a public prefix (for example NEXT_PUBLIC_). ## 3. Environment variables - List every environment variable the changed code reads. - Check each one is documented in .env.example (names only, never values). ## 4. Database access - If the diff adds or changes tables, check that Row Level Security (or the project's equivalent access control) is enabled and has a policy for each operation the app uses. ## 5. Report Reply with: - A one-line verdict: READY, READY WITH WARNINGS, or BLOCKED. - A table of checks with pass / warn / fail. - For each warn or fail: the file, the line, and a suggested fix. ``` A maintained copy of this skill, ready to install, is in our library as the [pre-deploy check skill for coding agents](/resources/pre-deploy-check-skill.html). This skill shows the habits that make skills work well: - **The description names the trigger phrases** ("ready to ship", "deploy", "merge", "production"), so the agent can match it to your requests. - **The steps are written as instructions**, with clear inputs and outputs. Codex's best-practice list says the same thing: "write imperative steps with explicit inputs and outputs." - **It does one job.** "Keep each skill focused on one job" is another of Codex's recommendations. - **It reports before it acts**, which keeps you in control of anything that changes code. To test it, open your agent in the repo and ask, "Is this branch ready to deploy?" If the skill doesn't trigger, sharpen the description first. You can also call it directly with `/pre-deploy-check` in Claude Code or Cursor, or `$pre-deploy-check` in Codex. ## Leveling up: scripts and references Once a skill works, you can make it more reliable: - **Add a `scripts/` folder** for steps that should behave the same way every time, such as a secret-scanning command. The spec asks that scripts be self-contained, document their dependencies and give helpful error messages ([spec](https://agentskills.io/specification)). - **Add `references/`** for long material such as your API conventions. The agent loads these files only when it needs them, so they cost almost nothing until then. - **Install skills other people have written.** For example, Supabase publishes agent skills for working with its platform, which you install with `npx skills add supabase/agent-skills` ([Supabase quickstart](https://supabase.com/docs/guides/getting-started/quickstarts/nextjs)). Read a third-party skill before you install it: Claude Code's docs warn that a skill can grant itself broad tool access through `allowed-tools`, so review those fields in any repository you don't control ([Claude Code docs](https://code.claude.com/docs/en/skills)). - **Use the built-in skill creators.** Codex ships a `$skill-creator`, and Cursor has a built-in `/create-skill` ([Codex](https://developers.openai.com/codex/skills), [Cursor](https://cursor.com/docs/context/skills)). ## Skills vs. AGENTS.md vs. MCP These three are easy to mix up: - **[AGENTS.md](/articles/what-is-agents-md-how-to-write-one.html) / CLAUDE.md** is always-on project context: build commands, code style, conventions. - **Skills** are procedures that load only when a task needs them. - **[MCP servers](/articles/mcp-explained-for-vibe-coders.html)** connect your agent to outside tools and data, like a database or an issue tracker. A good setup uses all three: short always-on context, a few focused skills, and only the MCP connections you actually need. ## Keep reading - [How to write an AGENTS.md file for your coding agent](/articles/what-is-agents-md-how-to-write-one.html) - [Code review skill for AI coding agents (SKILL.md download)](/resources/code-review-skill.html) - [Cursor vs Claude Code vs Codex: how to pick an AI coding agent](/articles/picking-a-coding-agent-cursor-claude-code-codex.html) ## FAQ ### What is an agent skill? An agent skill is a folder containing a SKILL.md file with a name, a description and instructions that an AI agent loads when a task needs them. It can also bundle scripts, references and assets. ### Where do I put a skill so my agent finds it? Put it in .agents/skills/ for Cursor and Codex, or .claude/skills/ for Claude Code. Cursor also reads .claude/skills/ and .codex/skills/ for compatibility. ### Which fields does SKILL.md need? Only name and description are required. The name is up to 64 lowercase letters, numbers and hyphens and must match the folder name. The description is up to 1,024 characters and says what the skill does and when to use it. ### How is a skill different from AGENTS.md? AGENTS.md is always-on project context loaded in every session. A skill is a procedure that loads only when a task matches its description, so it costs almost nothing until it is used. --- # How to add an MCP server to Cursor, Claude Code and Codex URL: https://codema.ai/articles/add-mcp-server-cursor-claude-code-codex.html Language: en Published: 2026-10-21 Description: Step-by-step: how to add an MCP server to Cursor, Claude Code and Codex, with copy-paste config for the Supabase and GitHub MCP servers. Connecting an MCP server is the moment your coding agent stops guessing about your database or your repos and starts reading the real thing. The catch is that Cursor, Claude Code and Codex each store MCP config in a different file with a slightly different format. This guide shows how to add an MCP server to Cursor, Claude Code and Codex, step by step, with the same two examples in each tool: the hosted Supabase server (remote, OAuth sign-in) and GitHub's remote MCP server (remote, token in a header). New to the protocol? Start with [what MCP is](/articles/mcp-explained-for-vibe-coders.html). ## Before you add an MCP server Three things to decide first: - **Remote or local.** Remote servers are a URL (Streamable HTTP). Local servers are a command your machine runs (stdio). Both examples here are remote. - **Project or global.** Project config can be committed so your team shares it. Global config follows you across projects but stays on your machine. - **Where the token lives.** Never paste a token straight into a file you commit. Each tool supports environment variable references, shown below. For Supabase, scope the server from the start with `project_ref` (one project only) and `read_only=true` (queries run as a read-only Postgres user). Supabase recommends both ([Supabase MCP docs](https://supabase.com/docs/guides/getting-started/mcp)). ## Add an MCP server to Cursor Cursor reads `.cursor/mcp.json` in your project, or `~/.cursor/mcp.json` for every project. Servers go under an `mcpServers` object. Remote servers take a `url` and optional `headers`, and any value can use `${env:NAME}`, `${workspaceFolder}` or `${userHome}` interpolation ([Cursor MCP docs](https://cursor.com/docs/context/mcp)). ```json { "mcpServers": { "supabase": { "url": "https://mcp.supabase.com/mcp?project_ref=YOUR_PROJECT_REF&read_only=true" }, "github": { "url": "https://api.githubcopilot.com/mcp/", "headers": { "Authorization": "Bearer ${env:GITHUB_PAT}" } } } } ``` Things to know: - **Tool approval is on by default.** Cursor asks before using MCP tools, and you can expand a call to see its arguments. - **`envFile` only works for local (stdio) servers.** For remote servers, set the variable in your shell profile or system environment. - **Debugging:** open the Output panel (Cmd+Shift+U or Ctrl+Shift+U) and pick "MCP Logs" to see connection errors, authentication issues and crashes. ## Add an MCP server to Claude Code Claude Code adds servers from the command line with `claude mcp add`. Each command writes to local scope (just you, this project) unless you add `--scope project`, which writes a `.mcp.json` you can commit, or `--scope user` for all your projects ([Claude Code MCP docs](https://code.claude.com/docs/en/mcp)). ```bash claude mcp add --scope project --transport http supabase \ "https://mcp.supabase.com/mcp?project_ref=YOUR_PROJECT_REF&read_only=true" claude mcp add --transport http github https://api.githubcopilot.com/mcp/ \ --header "Authorization: Bearer YOUR_GITHUB_PAT" ``` Then run `/mcp` inside Claude Code to sign in to Supabase and check that both servers connected. `claude mcp list`, `claude mcp get ` and `claude mcp remove ` manage them from the shell. If you edit `.mcp.json` by hand, a remote server needs `"type": "http"` next to its `url`. Use `${VAR}` or `${VAR:-default}` so the token stays out of the file: ```json { "mcpServers": { "supabase": { "type": "http", "url": "https://mcp.supabase.com/mcp?project_ref=YOUR_PROJECT_REF&read_only=true" }, "github": { "type": "http", "url": "https://api.githubcopilot.com/mcp/", "headers": { "Authorization": "Bearer ${GITHUB_PAT}" } } } } ``` Two limits worth knowing: Claude Code warns when an MCP tool returns more than 10,000 tokens and caps output at 25,000 tokens by default, which you can change with `MAX_MCP_OUTPUT_TOKENS`. And `claude mcp add` saves config without validating credentials, so a placeholder token is accepted and fails later. Run `/mcp` to confirm. ## Add an MCP server to Codex Codex keeps MCP servers in `~/.codex/config.toml`, or in a project's `.codex/config.toml` for trusted projects. The ChatGPT desktop app, the Codex CLI and the IDE extension share this config ([Codex MCP docs](https://developers.openai.com/codex/mcp)). From the CLI, Supabase documents this pair of commands: ```bash codex mcp add supabase --url "https://mcp.supabase.com/mcp?project_ref=YOUR_PROJECT_REF&read_only=true" codex mcp login supabase ``` Or write the config yourself. HTTP servers take a `url`, and `bearer_token_env_var` names the environment variable that holds the token: ```toml [mcp_servers.supabase] url = "https://mcp.supabase.com/mcp?project_ref=YOUR_PROJECT_REF&read_only=true" [mcp_servers.github] url = "https://api.githubcopilot.com/mcp/" bearer_token_env_var = "GITHUB_PAT" default_tools_approval_mode = "writes" ``` Useful options from the Codex docs: - **`enabled_tools` and `disabled_tools`** allow or block individual tools. - **`default_tools_approval_mode`** accepts `auto`, `prompt`, `writes` or `approve`. `writes` prompts for tools that aren't marked read-only. - **`startup_timeout_sec`** (default 10) and **`tool_timeout_sec`** (default 60) help with slow servers. - **`codex mcp list`** shows configured servers, and `/mcp` in the TUI shows what's connected. ## Test the connection Ask the agent something only the server can answer: ```text Using the Supabase MCP tools, list the tables in my project and tell me which ones don't have Row Level Security enabled. ``` If nothing happens, check the logs (Cursor's "MCP Logs", `/mcp` in Claude Code or Codex), confirm the environment variable is set in the shell that launched the tool, and restart the client after editing config by hand. ## Keep it safe Every connected server acts with your permissions. Claude Code's docs say to "verify you trust each server before connecting it", because servers that fetch external content can expose you to prompt injection. Keep approvals on for anything that writes, scope tokens to the minimum, and read our guide to [MCP security best practices](/articles/mcp-security-best-practices.html) before you connect anything to production. All three config files from this guide, ready to edit, are in our [MCP config starter](/resources/mcp-config-starter.html). ## Keep reading - [What is MCP? The Model Context Protocol explained for vibe coders](/articles/mcp-explained-for-vibe-coders.html) - [How to run coding agents safely: permissions, sandboxes and secrets](/articles/run-coding-agents-safely-permissions-sandboxes.html) - [Supabase RLS audit skill for coding agents](/resources/supabase-rls-audit-skill.html) ## FAQ ### Where is the MCP config file in Cursor? Cursor reads .cursor/mcp.json in your project and ~/.cursor/mcp.json for all projects. Servers go under an mcpServers object. ### How do I add an MCP server to Claude Code? Run claude mcp add --transport http with a name and the server URL. Add --scope project to write a .mcp.json file your team can commit, then run /mcp to sign in. ### Where does Codex store MCP servers? Codex stores MCP servers in ~/.codex/config.toml, or in .codex/config.toml for trusted projects. The ChatGPT desktop app, Codex CLI and IDE extension share this config. ### Why does my MCP server not connect? Check the logs (MCP Logs in Cursor, /mcp in Claude Code or Codex), confirm the environment variable is set in the shell that launched the tool, and restart the client after editing config by hand. --- # How to back up a Supabase database and export your data URL: https://codema.ai/articles/back-up-supabase-database.html Language: en Published: 2026-10-21 Description: How to back up a Supabase database: what each plan backs up, how to export with supabase db dump, how to restore, and what backups leave out. Your app's code lives in Git. Your app's data lives in one Postgres database, and on a free Supabase project nobody is backing it up for you. If you vibe coded the app in a weekend, this is the step that's easiest to skip and most painful to miss. Here's how to back up a Supabase database on any plan, and how to restore it. This guide explains how to back up a Supabase database: what Supabase backs up automatically on each plan, how to export your own backup with the Supabase CLI, how to restore it, and what a backup does not include. The commands come straight from Supabase's documentation, linked throughout. ## What Supabase backs up automatically Supabase's [backup docs](https://supabase.com/docs/guides/platform/backups) set out what each plan gets: | Plan | Automatic daily backups | | --- | --- | | Free | None. Supabase recommends regular exports with the CLI and off-site backups. | | Pro | Last 7 days | | Team | Last 14 days | | Enterprise | Up to 30 days | Daily backups appear under **Database > Backups** in the Dashboard, and you can restore a project to any of them. Restoring makes the project inaccessible while it runs, so plan for downtime. For finer recovery, Pro, Team and Enterprise projects can add **Point-in-Time Recovery (PITR)**, which lets you restore to a chosen moment with up to seconds of granularity. It needs at least a Small compute add-on, it replaces daily backups when enabled, and it's priced by retention period. Check Supabase's pricing table on the backups page before you turn it on. ## What a Supabase backup does not include Read this part twice. According to Supabase: - **Storage objects aren't in database backups.** The database only holds metadata about files uploaded through the Storage API, so restoring a backup doesn't restore deleted files. - **Custom role passwords aren't stored** in daily backups. After a restore, you reset them. - **Deleting a project deletes its backups.** When you delete a project, Supabase permanently removes all associated data, including backups. That's irreversible. The last point is the strongest argument for keeping your own copy somewhere outside Supabase, whatever plan you're on. ## How to back up a Supabase database with the CLI Supabase documents a three-file logical backup using `supabase db dump` ([Supabase backup and restore with the CLI](https://supabase.com/docs/guides/platform/migrating-within-supabase/backup-restore)). You need: 1. The [Supabase CLI](https://supabase.com/docs/reference/cli/supabase-db-dump) and **Docker Desktop**, which the CLI dump uses. 2. Your connection string from **Connect** on the project dashboard. Supabase says to use the Session pooler string by default, or the direct string if your network supports IPv6 or you have the IPv4 add-on. 3. Your database password in place of `[YOUR-PASSWORD]`. Then run the three commands, replacing `[CONNECTION_STRING]`: ```bash supabase db dump --db-url [CONNECTION_STRING] -f roles.sql --role-only supabase db dump --db-url [CONNECTION_STRING] -f schema.sql supabase db dump --db-url [CONNECTION_STRING] -f data.sql --use-copy --data-only -x "storage.buckets_vectors" -x "storage.vector_indexes" ``` You now have the roles, the schema and the data as plain SQL files. Treat them like the database itself: they contain your users' data, so store them encrypted, somewhere access-controlled, and never in your Git repository. Our guide to [Git basics for vibe coders](/articles/git-github-basics-for-vibe-coders.html) shows how to keep files like these out of commits with `.gitignore`. If your project uses Edge Functions, back up their code too. Supabase documents `supabase functions download YOUR_FUNCTION_NAME --project-ref your_project_ref`, which doesn't include import maps or `deno.json` files, so keep those in your repository. ## How to restore a Supabase backup To restore into a project you created yourself, Supabase uses `psql` with the three files in order: ```bash psql \ --single-transaction \ --variable ON_ERROR_STOP=1 \ --file roles.sql \ --file schema.sql \ --command 'SET session_replication_role = replica' \ --file data.sql \ --dbname [CONNECTION_STRING] ``` `--single-transaction` and `ON_ERROR_STOP=1` mean the restore either completes or changes nothing. If the old database used Realtime, re-enable publications on the needed tables under **Database > Publications** afterwards. ## Make backups a habit, not a one-off A backup you've never restored is a hope, not a backup. A simple routine: - **Export on a schedule.** Weekly for a side project, daily for anything with paying customers. Ask your agent to write a script that runs the three commands and names files by date, and have a human review where the files end up. - **Store copies off-site**, outside your Supabase organization, so deleting or losing access to a project doesn't take the backups with it. - **Back up Storage separately** if users upload files. - **Test a restore** into a fresh project every few months, and time it. That number is how long you'd be down. Being able to export and restore your data whenever you want is a big part of [owning your code and data](/articles/own-your-code-and-data-building-with-ai.html), and Quebec's Law 25 data portability rules make it a compliance question too. ## Keep reading - [How to vibe code a SaaS with Supabase and Vercel in a weekend](/articles/vibe-code-saas-supabase-vercel-weekend.html) - [Supabase RLS audit skill for coding agents](/resources/supabase-rls-audit-skill.html) - [How to build a bilingual app for Quebec with AI](/articles/building-with-ai-in-french-quebec.html) ## FAQ ### Does Supabase back up free projects? No. Supabase automatically backs up Pro, Team and Enterprise projects. For free projects, Supabase recommends regular exports with the CLI db dump command and off-site backups. ### How do I export my Supabase database? Install the Supabase CLI and Docker, then run supabase db dump three times with your connection string: once with --role-only, once for the schema, and once with --data-only and --use-copy. ### Do Supabase backups include Storage files? No. Database backups only include metadata about files stored through the Storage API, so back up Storage objects separately. ### What happens to backups if I delete a Supabase project? They are deleted. Supabase permanently removes all data for a deleted project, including backups, and the action is irreversible. --- # GA4 predictive audiences: how they work and how to use them in Google Ads URL: https://codema.ai/articles/ga4-predictive-audiences-google-ads.html Language: en Published: 2026-10-21 Description: GA4 predictive audiences target users likely to buy or churn. The requirements, how to create one, and how to use it in Google Ads, from Google docs. Most remarketing lists are built on what people already did: visited the pricing page, added to cart, opened an email. GA4 predictive audiences flip that around. Google Analytics uses machine learning to estimate what each user is likely to do next, and you can target the users most likely to buy, or most likely to leave. This guide explains how GA4 predictive audiences work, the data your property needs before they unlock, how to create one and how to use it in Google Ads. Every requirement comes from Google's own help pages, linked throughout. ## What GA4 predictive metrics are A predictive audience is "an audience with at least one condition based on a predictive metric" ([Google Analytics Help](https://support.google.com/analytics/answer/9805833)). GA4 calculates these metrics ([predictive metrics](https://support.google.com/analytics/answer/9846734)): | Metric | What it predicts | | --- | --- | | **Purchase probability** | The probability that a user active in the last 28 days logs a specific key event within the next 7 days | | **Churn probability** | The probability that a user active in the last 7 days is not active in the next 7 days | | **Predicted revenue** | Revenue expected from all purchase key events in the next 28 days from a user active in the last 28 days | Purchase probability and predicted revenue currently work with the `purchase` and `in_app_purchase` events (`ecommerce_purchase` is still processed, but Google now recommends `purchase`). Predictions are generated once per day for each active user. Google also says it does not use the standard GA4 demographic dimensions to train these models. They are trained on behavioral event data from your site and app. ## GA4 predictive audiences requirements This is where most small sites get stuck. To train the models, GA4 needs enough positive and negative examples ([predictive metrics](https://support.google.com/analytics/answer/9846734)): - **Volume:** in the last 28 days, over a seven-day period, at least 1,000 returning users must have triggered the predictive condition (a purchase, or churn) and at least 1,000 returning users must not have. - **Sustained model quality:** quality has to hold over time. If it drops below the minimum, GA4 stops updating that prediction and it may become unavailable. - **Purchase events with value and currency:** to be eligible for purchase probability and predicted revenue, send the `purchase` event (and/or `in_app_purchase`) with the `value` and `currency` parameters. You can check eligibility in the predictive section of the suggested audience templates. If your site isn't there yet, the useful work is upstream: clean ecommerce events and consistent [UTM tracking](/articles/utm-tracking-setup-guide.html) so the data is ready when volume arrives. ## How to create a predictive audience in GA4 Google's steps ([predictive audiences](https://support.google.com/analytics/answer/9805833)): 1. In **Admin**, under "Data display", click **Audiences**. You need the Marketer role or above at the property level. 2. Click **New audience**. 3. Under "Suggested audiences", click **Predictive**. Templates that meet the prerequisites are labeled "Ready to use". 4. Pick a template and adjust it in the audience builder, or build a custom audience and choose a predictive metric as a condition. For each predictive condition you can choose **Most likely** (the top N% of users), **Least likely** (the bottom N%) or a **Custom** percentage range. Two suggested templates show how the defaults work: - **Likely 7-day purchasers:** users whose purchase probability is above the 90th percentile, roughly the top 10%. - **Likely 7-day churning users:** the default churn configuration includes the 80th to 100th percentile, the top 20%. A wider range includes more users, but a bigger share of them are less likely to do the thing you predicted. Start with the default and widen it only if the audience is too small to serve ads. ## How to use predictive audiences in Google Ads Predictive audiences are automatically shared with advertising accounts linked to your property, such as Google Ads, Display & Video 360 and Search Ads 360 ([predictive audiences](https://support.google.com/analytics/answer/9805833)). Once your GA4 property and Google Ads account are linked, the audience appears in Google Ads and you can add it to campaigns. Google suggests two main uses: - **Remarketing to likely purchasers.** Users close to converting may need one last, relevant nudge. - **Re-engaging likely churners.** These users showed interest before. Remind them of the value you offer, or make a specific offer. Make sure Google Ads auto-tagging is on. Google says it is needed to import Google Ads cost and campaign data into Analytics and to import key events into Google Ads, and it is on by default for new accounts ([Google Ads Help](https://support.google.com/google-ads/answer/3095550)). One caveat to plan around: if your property becomes ineligible and new predictions stop, exported predictive audiences stop accumulating new users. Check eligibility before you build a campaign that depends on one. ## Test it before you trust it A prediction is a ranking, not a result. Run the predictive audience against a comparable non-predictive audience, or as a controlled experiment, and compare cost per acquisition on real conversions. The same rule applies to ad creative: our guide to [predictive creative testing](/articles/predictive-creative-testing-ai-ad-creatives.html) shows how to confirm AI predictions with Google Ads experiments. ## Keep reading - [UTM tracking setup: a naming guide for AI-built sites](/articles/utm-tracking-setup-guide.html) - [Predictive creative testing: how to test AI ad creatives before you spend](/articles/predictive-creative-testing-ai-ad-creatives.html) - [Own your code and data: why it matters when you build with AI](/articles/own-your-code-and-data-building-with-ai.html) ## FAQ ### What are GA4 predictive audiences? GA4 predictive audiences are audiences with at least one condition based on a predictive metric, such as purchase probability or churn probability, which Google Analytics calculates with machine learning. ### Why are predictive metrics not available in my GA4 property? Usually because of volume. GA4 needs at least 1,000 returning users who triggered the condition and 1,000 who did not, over a seven-day period in the last 28 days, and sustained model quality. ### How do I use a GA4 predictive audience in Google Ads? Link your GA4 property to Google Ads. Predictive audiences are shared automatically with linked advertising accounts, and you can then add them to campaigns. ### Who can create predictive audiences in GA4? You need the Marketer role or above at the property level. Create them in Admin, Audiences, New audience, then Predictive under suggested audiences. --- # Git and GitHub basics for vibe coders: never lose AI-written code URL: https://codema.ai/articles/git-github-basics-for-vibe-coders.html Language: en Published: 2026-10-21 Description: Git and GitHub basics for vibe coders: the commands you need, a branch-per-task workflow for coding agents, .gitignore for secrets, and push protection. If you build with an AI agent, Git is your undo button. The agent can rewrite twenty files in a minute. Without version control, a bad change means rebuilding from memory. With it, you look at the diff and either keep the change or throw it away in one command. These Git and GitHub basics are all you need to start. This guide covers the Git and GitHub basics for vibe coders: the handful of commands you need, a branch-per-task workflow that works well with coding agents, how to keep secrets and backups out of your repository with `.gitignore`, and the GitHub settings that catch leaked keys before they go public. ## Why Git matters more when AI writes the code Coding agent vendors build their safety advice around Git. OpenAI's Codex docs say Codex "works best with a version control workflow": work on a feature branch, keep `git status` clean before delegating, and commit frequently so you can roll back in small increments ([Codex security docs](https://developers.openai.com/codex/agent-approvals-security)). Codex even protects the `.git` folder as read-only in its default sandbox. The reason is simple. Every agent change becomes a diff you can read, test and reverse. That turns "the AI broke my app" from a crisis into a two-minute fix. ## Git and GitHub basics: the commands vibe coders need You don't need to master Git. These cover most days: ```bash git status # what changed since the last commit git diff # the exact lines that changed git switch -c add-invoices # start a new branch for one task git add -A # stage every change git commit -m "Add invoices list and create form" git push -u origin add-invoices git switch main # go back to the main branch git restore path/to/file.ts # throw away uncommitted changes to one file ``` The official [Git documentation](https://git-scm.com/docs) explains each command in full. The habit matters more than the commands: **commit before you hand the agent a task, and commit again when the task works.** Then any bad step is one `git restore` or `git switch` away. ## A branch-per-task workflow for AI coding agents Use the same loop for every feature: 1. **Start clean.** `git status` should say there's nothing to commit. 2. **Create a branch** named after the task: `git switch -c fix-login-redirect`. 3. **Give the agent one task.** Small tasks produce small diffs you can actually review. 4. **Read the diff** with `git diff` or in your editor. Our [checklist for reviewing AI-generated code](/articles/review-ai-written-code-before-production.html) tells you what to look at first. 5. **Commit and push** the branch, then open a pull request on GitHub. 6. **Merge when it's right.** If you deploy with Vercel, every branch and pull request gets its own preview deployment with its own URL, and merging to `main` deploys to production ([Vercel environments](https://vercel.com/docs/deployments/environments)). Before you open the pull request, our [AI code review skill](/resources/code-review-skill.html) can check the diff for the riskiest problems first. ## Keep secrets out of Git with .gitignore A `.gitignore` file in your repository's root tells Git which files and folders to ignore when you commit ([GitHub Docs](https://docs.github.com/en/get-started/git-basics/ignoring-files)). GitHub maintains official templates for most languages and frameworks in the [github/gitignore](https://github.com/github/gitignore) repository. For a typical Next.js and Supabase app, make sure these are ignored: ```text # Secrets and local config .env .env.local .env*.local # Build output and dependencies node_modules/ .next/ # Database exports *.sql.gz backups/ ``` Two details trip people up: - **`.gitignore` doesn't affect files Git already tracks.** If you committed `.env.local` before adding the rule, untrack it with `git rm --cached .env.local`, then commit. GitHub documents this as the way to ignore a file that's already checked in. - **Untracking doesn't erase history.** If a real key was committed, assume it's exposed and rotate it at the provider. That's faster and safer than rewriting history. Commit a `.env.example` with variable names only, so the agent and your teammates know what the app expects without seeing any values. ## Turn on GitHub's secret protection GitHub can stop some leaks before they happen: - **Push protection for users** is on by default and stops you from pushing secrets to public repositories on GitHub. You can manage it under Settings > Code security ([GitHub Docs](https://docs.github.com/en/code-security/secret-scanning/working-with-secret-scanning-and-push-protection/push-protection-for-users)). - **Push protection for repositories** blocks pushes containing secrets from reaching a specific repository, whoever pushes. It's off by default, an admin enables it, and it requires GitHub Secret Protection ([about push protection](https://docs.github.com/en/code-security/secret-scanning/introduction/about-push-protection)). Don't treat these as your only defence. They recognize known secret formats, not every value that should stay private. ## Your repository is your ownership A repository in an account your business controls is the foundation of [owning your code and data](/articles/own-your-code-and-data-building-with-ai.html). Pair it with regular [database backups](/articles/back-up-supabase-database.html) and you can rebuild your whole product from what you hold. ## Keep reading - [How to run coding agents safely: permissions, sandboxes and secrets](/articles/run-coding-agents-safely-permissions-sandboxes.html) - [What is AGENTS.md, and how to write one](/articles/what-is-agents-md-how-to-write-one.html) - [Pre-deploy check skill for coding agents](/resources/pre-deploy-check-skill.html) ## FAQ ### Do I need Git if an AI agent writes my code? Yes. Git turns every agent change into a diff you can review and reverse. OpenAI recommends working on a feature branch, keeping git status clean and committing frequently when using Codex. ### How do I stop .env files from being committed? Add .env and .env*.local to a .gitignore file in the repository root. If a file is already tracked, untrack it with git rm --cached and commit the change. ### What should I do if I committed an API key? Rotate the key at the provider right away, then remove it from the code and untrack the file. Assume a committed key is exposed even if you delete it later. ### What is GitHub push protection? Push protection blocks pushes that contain supported secrets. Push protection for users is on by default for public repositories, and push protection for repositories requires GitHub Secret Protection. --- # MCP security best practices: how to use MCP servers without leaking data URL: https://codema.ai/articles/mcp-security-best-practices.html Language: en Published: 2026-10-21 Description: MCP security best practices for vibe coders: prompt injection risks, what the MCP spec requires, and a checklist to use MCP servers without leaking data. MCP makes your coding agent far more useful, because it can now read your database, your tickets and your repos. It also gives anyone who can put text in front of that agent a new way to reach those systems. MCP security is mostly about closing that gap without giving up the convenience. This guide covers MCP security best practices for people who use MCP servers, not only people who build them: the main risks, what the MCP specification requires, and a checklist you can apply today. Everything is sourced from the [MCP specification](https://modelcontextprotocol.io/specification/2025-06-18/basic/security_best_practices) and from the docs of the tools you probably use. ## Why MCP security is different A normal integration does one fixed thing. An MCP server hands a language model a set of tools, and the model decides when to call them based on everything in its context. The spec says tools are "model-controlled", which is exactly why it asks for a human in the loop ([MCP tools spec](https://modelcontextprotocol.io/specification/2025-06-18/server/tools)). Three facts follow from that: 1. **The server acts with your permissions.** Supabase says its MCP server runs with your developer permissions and should only be used as an internal tool, never handed to customers ([Supabase MCP](https://supabase.com/docs/guides/getting-started/mcp)). 2. **Anything the agent reads can carry instructions.** A support ticket, a web page, a code comment or a database row can contain text written to steer the agent. 3. **Tool descriptions are claims, not guarantees.** The spec says clients "MUST consider tool annotations to be untrusted unless they come from trusted servers." ## The biggest MCP risk: prompt injection through data Supabase's docs walk through a realistic attack. A customer writes instructions into a support ticket. A developer later asks their agent to summarize open tickets. The agent reads the hidden instructions, follows them and uses its database access to leak data ([Supabase MCP](https://supabase.com/docs/guides/getting-started/mcp)). Claude Code's docs give the same warning: servers that fetch external content "can expose you to prompt injection risk" ([Claude Code MCP](https://code.claude.com/docs/en/mcp)). Nothing in that attack needs a bug in MCP itself. It needs three things together: access to private data, exposure to untrusted content, and a way to send data out. Remove any one and the attack gets much harder. That's the logic behind most of the checklist below. ## What the MCP spec requires The specification's security best practices are written mainly for people who build servers and clients, but they tell users what to expect and what to avoid ([MCP security best practices](https://modelcontextprotocol.io/specification/2025-06-18/basic/security_best_practices)): - **No token passthrough.** "MCP servers MUST NOT accept any tokens that were not explicitly issued for the MCP server." A server that simply forwards your token to another API is a red flag. - **No sessions as authentication.** "MCP Servers MUST NOT use sessions for authentication", and session IDs must be secure and non-deterministic. - **Consent before running local servers.** When a client offers one-click setup of a local server, it "MUST" show the exact command that will run, without truncation, flag it as potentially dangerous and require your explicit approval. - **Confused deputy, SSRF and OAuth URL validation.** The spec covers proxy servers that can be tricked into acting for the wrong client, servers that can be induced to request internal addresses, and malicious authorization URLs. - **Scope minimization.** Ask for the narrowest permissions a task needs, not everything a token can do. On the client side, the tools spec says applications SHOULD show which tools are exposed, indicate clearly when a tool is invoked, ask for confirmation on sensitive operations and show tool inputs to the user before calling the server ([MCP tools spec](https://modelcontextprotocol.io/specification/2025-06-18/server/tools)). ## MCP security checklist for vibe coders **Before you connect a server** - [ ] It comes from a source you trust: the vendor's official docs or repository. Cursor's guidance is to verify the source, review permissions, use restricted API keys and audit code for critical integrations ([Cursor MCP](https://cursor.com/docs/context/mcp)). - [ ] You know whether it runs locally (a command on your machine) or remotely (a URL), and you've read the exact command for a local server. - [ ] Its token is scoped to the minimum: one project, read-only where possible, short-lived where the provider allows it. **When you configure it** - [ ] Tokens are referenced from environment variables, never pasted into a committed file. Cursor uses `${env:NAME}`, Claude Code uses `${VAR}` and Codex uses `bearer_token_env_var`. Our guide to [adding an MCP server to Cursor, Claude Code and Codex](/articles/add-mcp-server-cursor-claude-code-codex.html) shows each one. - [ ] Supabase servers use `project_ref` and `read_only=true`, and only the feature groups you need, for example `features=database,docs` ([Supabase MCP](https://supabase.com/docs/guides/getting-started/mcp)). - [ ] In Codex, risky servers use `default_tools_approval_mode = "writes"` or `"prompt"`, and `disabled_tools` blocks tools you never need ([Codex MCP](https://developers.openai.com/codex/mcp)). **While you work** - [ ] Tool approvals stay on. Cursor asks before using MCP tools by default. Read the arguments before approving anything that writes. - [ ] You don't point an agent with write access at untrusted content (tickets, emails, scraped pages) in the same session. - [ ] Production data stays out of reach unless the task needs it. Develop against a separate project. **Afterwards** - [ ] Remove servers you no longer use. Fewer tools means less for an attacker to steer and less context for the agent to wade through. - [ ] Rotate any token that was ever pasted into a chat, a config file or a log. ## Where MCP fits with the rest of your agent safety MCP is one layer. Permission modes, sandboxes and deny rules decide what the agent can do on your machine. Our guide to [running coding agents safely](/articles/run-coding-agents-safely-permissions-sandboxes.html) covers those settings for Claude Code and Codex. Together they let you give an agent real access without giving it the keys to everything. ## Keep reading - [What is MCP? The Model Context Protocol explained for vibe coders](/articles/mcp-explained-for-vibe-coders.html) - [MCP config starter with a safety checklist](/resources/mcp-config-starter.html) - [Claude Code hooks starter: block risky commands](/resources/claude-code-hooks-starter.html) ## FAQ ### Is MCP secure? MCP can be used securely, but a connected server acts with your permissions. Security depends on trusted servers, narrowly scoped tokens, tool approvals and keeping untrusted content away from agents with write access. ### What is prompt injection in MCP? Prompt injection is when text the agent reads, such as a support ticket or web page, contains instructions that steer the agent into misusing its tools, for example leaking database data. ### What is token passthrough? Token passthrough is when an MCP server accepts a token issued for another service and forwards it. The MCP spec forbids it: servers must not accept tokens that were not explicitly issued for them. ### Should I connect MCP servers to production data? Only when the task needs it. Develop against a separate project, use read-only access where possible, and keep approvals on for any tool that writes. --- # How to run coding agents safely: permissions, sandboxes and secrets URL: https://codema.ai/articles/run-coding-agents-safely-permissions-sandboxes.html Language: en Published: 2026-10-21 Description: How to run coding agents safely with Claude Code permission modes, Codex sandbox and approval settings, deny rules, and habits that keep secrets out of reach. A coding agent that can edit files and run commands can also delete files, leak a key or push something you didn't mean to ship. You don't fix that by turning the agent off. You fix it by deciding, ahead of time, what it may do without asking. This guide shows how to run coding agents safely with the controls Claude Code and Codex already ship: permission modes, sandboxes, approval policies and deny rules. It also covers the habits that keep secrets out of reach. Everything here comes from the vendors' own documentation, linked as we go. ## Three questions to run coding agents safely Every safety setting answers one of these: 1. **What can the agent touch?** Files, folders, the network. This is the sandbox. 2. **When must it ask first?** Edits, shell commands, network calls. This is the permission mode or approval policy. 3. **What is never allowed, no matter what?** Deleting your home folder, pushing to `main`, reading `.env`. These are deny rules and protected paths. Get these three right and you can let an agent work for long stretches without approving every keystroke. ## Claude Code permission modes Claude Code calls its main control a permission mode. You switch modes with Shift+Tab in the CLI, the mode indicator in VS Code, or the mode selector in the desktop app ([Claude Code permission modes](https://code.claude.com/docs/en/permission-modes)). The docs list what runs without asking in each mode: | Mode | What runs without asking | Best for, per the docs | | --- | --- | --- | | Manual (`default`) | Reads only | Reviewing every action yourself, sensitive work | | `acceptEdits` | Reads, file edits and common filesystem commands | Iterating on code you're reviewing | | `plan` | Reads, plus classifier-approved commands when auto mode is available | Exploring a codebase before changing it | | `auto` | Everything, with background safety checks by a classifier | Long tasks, reducing prompt fatigue | | `dontAsk` | File reads and pre-approved tools; anything that would prompt is denied | Locked-down CI and scripts | | `bypassPermissions` | Everything | Isolated containers and VMs only | Two details matter more than the table: - **Auto mode is not a guarantee.** The docs say plainly that auto mode "reduces permission prompts but does not guarantee safety". With Claude Code v2.1.283 or later, auto mode is the built-in starting mode for interactive terminal and VS Code sessions, so check which mode you're in before a sensitive task. - **Deny rules always win.** "Deny rules block in every mode, including `bypassPermissions`." If something must never happen, write a deny rule instead of hoping a mode will catch it. Writes to a small set of protected paths, which keep your repository state and Claude Code's own configuration safe, are also never auto-approved outside `bypassPermissions`. Instruction files don't replace these controls. Claude Code's docs describe CLAUDE.md as context, not enforced configuration, and recommend a PreToolUse hook to block an action regardless of what Claude decides ([Claude Code memory docs](https://code.claude.com/docs/en/memory)). ## Codex sandbox and approval policies Codex splits the same idea into two settings: a sandbox that limits what the agent can touch, and an approval policy that decides when it must stop and ask ([Codex security docs](https://developers.openai.com/codex/agent-approvals-security)). - **Network access is off by default.** Locally, Codex uses an OS-enforced sandbox that typically limits it to the current workspace. - **The Auto preset** is `--sandbox workspace-write --ask-for-approval on-request`. Codex can read files, make edits and run commands in the working directory, and asks before editing outside the workspace or running commands that need the network. - **Read-only** (`--sandbox read-only`) is the mode for chatting and planning without changes. - **Protected paths** stay read-only even in `workspace-write`: the `.git` folder, plus `.agents` and `.codex` when they exist. - **`--yolo`** is the alias for `--dangerously-bypass-approvals-and-sandbox`: no sandbox and no approvals. The docs mark it "Elevated Risk" and "not recommended". If a task really needs the network in the default sandbox, enable it explicitly in `config.toml` instead of dropping the sandbox: ```toml [sandbox_workspace_write] network_access = true ``` One migration note: Codex no longer supports `approval_policy = "untrusted"`, and the docs say the retired setting can stop Codex from starting. Remove it from old config files. ## Keep secrets out of the agent's reach Most leaks don't need a malicious agent. They happen because a key was sitting where the agent could read it, paste it or commit it. - **Keep secrets in environment variables**, not in code, prompts, AGENTS.md or MCP config files. Cursor supports `${env:NAME}` in `mcp.json`, Claude Code expands `${VAR}` in `.mcp.json`, and Codex can read a bearer token from an environment variable with `bearer_token_env_var` ([Cursor MCP](https://cursor.com/docs/context/mcp), [Claude Code MCP](https://code.claude.com/docs/en/mcp), [Codex MCP](https://developers.openai.com/codex/mcp)). - **Never give an agent a production secret it doesn't need.** On Supabase, the secret key bypasses Row Level Security. Develop against a separate project, and connect the Supabase MCP server with `read_only=true` and a `project_ref` ([Supabase MCP](https://supabase.com/docs/guides/getting-started/mcp)). - **Leave GitHub push protection on.** Push protection for users is on by default and blocks supported secrets when you push to public repositories ([GitHub Docs](https://docs.github.com/en/code-security/secret-scanning/working-with-secret-scanning-and-push-protection/push-protection-for-users)). - **Rotate first, clean up second.** If a key reaches a commit, revoke it right away. Our guide to [Git and GitHub basics for vibe coders](/articles/git-github-basics-for-vibe-coders.html) covers `.gitignore` and untracking files. ## A safe default setup Here's the setup we'd start with for a solo builder or small team: 1. **Work on a branch with a clean `git status`.** Then every agent change is a diff you can review or throw away. 2. **Start in a mode that asks before edits** (Manual or `acceptEdits` in Claude Code, read-only or Auto in Codex) until you trust the task. 3. **Add deny rules** for anything that must never happen, such as reading `.env` files or pushing to `main`. Our [Claude Code safe settings starter](/resources/claude-code-safe-settings.html) has these rules ready to copy, and the [Claude Code hooks starter](/resources/claude-code-hooks-starter.html) adds a PreToolUse hook as a second layer. 4. **Keep the network off** unless the task needs it, and enable it per project. 5. **Scope every MCP server** to one project, read-only where possible. See [MCP security best practices](/articles/mcp-security-best-practices.html). 6. **Reserve full bypass modes for throwaway containers or VMs**, never your laptop with your SSH keys and browser sessions on it. 7. **Review the diff before you merge.** Our [checklist for reviewing AI-generated code](/articles/review-ai-written-code-before-production.html) puts the riskiest checks first. ## Keep reading - [MCP security: how to use MCP servers without leaking data](/articles/mcp-security-best-practices.html) - [Cursor vs Claude Code vs Codex: how to pick an AI coding agent](/articles/picking-a-coding-agent-cursor-claude-code-codex.html) - [Pre-deploy check skill for coding agents](/resources/pre-deploy-check-skill.html) ## FAQ ### What is the safest way to run a coding agent? Work on a branch with a clean git status, start in a mode that asks before edits, add deny rules for anything that must never happen, keep network access off unless needed, and review the diff before merging. ### What does bypassPermissions do in Claude Code? bypassPermissions lets everything run without asking. Anthropic says it is for isolated containers and VMs only. Deny rules still block in that mode. ### Does Codex have internet access by default? No. Codex runs with network access turned off by default. In the workspace-write sandbox you can enable it with network_access = true under [sandbox_workspace_write] in config.toml. ### What is --yolo in Codex? --yolo is the alias for --dangerously-bypass-approvals-and-sandbox, which runs Codex with no sandbox and no approvals. OpenAI marks it as elevated risk and not recommended. --- # UTM tracking setup: a UTM naming guide for AI-built sites URL: https://codema.ai/articles/utm-tracking-setup-guide.html Language: en Published: 2026-10-21 Description: A UTM tracking setup for GA4: what each UTM parameter does, a lowercase naming convention to copy, auto-tagging rules, and launch checks for AI-built sites. You launched the site, posted it everywhere and ran a few ads. A week later, GA4 shows a pile of "(direct) / (none)" traffic and three different spellings of the same campaign. The fix is boring and it works: a UTM tracking setup that everyone, including your AI agent, follows the same way. This UTM tracking setup guide covers what each UTM parameter does in Google Analytics 4, a naming convention you can copy, how UTMs interact with Google Ads auto-tagging, and the checks an AI-built site needs so the parameters survive the trip to your landing page. ## What UTM parameters are UTM parameters are tags you add to a link so Analytics knows where a visit came from. When someone clicks a tagged link, the values are sent to Analytics and show up in the **Acquisition > Traffic acquisition** report as session source, medium and campaign ([Google Analytics Help](https://support.google.com/analytics/answer/10917952)). GA4 recognizes these parameters: | Parameter | What it's for | Google's example | | --- | --- | --- | | `utm_source` | The referrer | google, newsletter4, billboard | | `utm_medium` | The marketing medium | cpc, banner, email | | `utm_campaign` | The campaign, product or promo | spring_sale | | `utm_id` | Campaign ID, matching any uploaded campaign data | | | `utm_term` | Paid keyword | | | `utm_content` | Which creative or link was clicked | two CTAs in one email | | `utm_source_platform` | The platform directing the traffic | Search Ads 360 | | `utm_creative_format` | Type of creative | Not currently reported in GA4 | | `utm_marketing_tactic` | Targeting criteria | Not currently reported in GA4 | Google's rule of thumb: always use `utm_source`, `utm_medium` and `utm_campaign` together. ## A UTM naming convention you can copy Google's UTM best practices boil down to consistency ([Google Analytics Help](https://support.google.com/analytics/answer/10917952)): - **Use lowercase everywhere.** Values are case sensitive: "Meta" and "meta" are different rows, and so are "SpringSale" and "Spring_Sale". - **One source per platform.** Pick one value per platform and sub-platform and never vary it. - **One medium per channel.** For example `email`, `cpc` or `paid_social`, and keep it identical across campaigns. - **One campaign name per campaign**, matching the campaign name in the ad platform. - **Unique `utm_content` per creative**, so you can compare variations. A simple scheme that follows those rules: ```text utm_source = platform (google, meta, linkedin, newsletter) utm_medium = channel (cpc, paid_social, email, social) utm_campaign = yyyy-mm_name (2026-10_launch) utm_content = creative id (hook-a_video-15s) ``` A finished link looks like this: ```text https://example.com/pricing?utm_source=newsletter&utm_medium=email&utm_campaign=2026-10_launch&utm_content=hero-cta ``` Build links with Google's [Campaign URL Builder](https://ga-dev-tools.google/campaign-url-builder/) or a shared spreadsheet, and keep a list of allowed values so nobody invents a new one at 11 p.m. on launch night. ## UTMs and Google Ads auto-tagging For Google Ads, use auto-tagging instead of manual UTMs where you can. Auto-tagging adds a `gclid` parameter to the URLs people click through from your ads. Google says it's needed to track conversions on all browsers, import key events into Google Ads and bring Google Ads cost and campaign data into Analytics. It's on by default for new accounts ([Google Ads Help](https://support.google.com/google-ads/answer/3095550)). If you add manual UTMs to Google Ads links anyway, know this: in GA4, auto-tagging takes priority over manual tagging, and there's no override option. Keep manual UTMs for everything that isn't Google Ads: email, social posts, partner links and other ad platforms. ## UTM tracking checks for AI-built sites Sites built quickly with an AI agent often add redirects, middleware and client-side routing without anyone thinking about query strings. Ask your agent to check these before launch: ```text Check that marketing query parameters survive every redirect and route change on this site: - utm_source, utm_medium, utm_campaign, utm_content, utm_term, gclid - Test: the root URL, a locale redirect, a trailing-slash redirect, and any auth redirect a landing page might trigger. - List every redirect, rewrite or middleware rule, and whether it keeps the query string. Report only. Don't change code yet. ``` Google specifically warns that if your site uses redirects, the GCLID must be passed to the final landing page, and that some sites reject unknown URL parameters and show an error page ([Google Ads Help](https://support.google.com/google-ads/answer/3095550)). Click one of your own tagged links and confirm the visit appears in the GA4 Traffic acquisition report with the right source, medium and campaign. Two more checks while you're there: - **Internal links never carry UTMs.** Tag links that bring people to your site, not links between your own pages, or a visitor who is already on the site gets attributed to a new campaign. - **UTMs aren't in page-path reports.** Google notes that UTM values are left out of "Landing page + query string" and "Page path + query string" and appear in "Page location" instead. ## Turn UTMs into decisions Clean UTMs pay off later. They let you compare channels honestly, feed reliable data into [GA4 predictive audiences](/articles/ga4-predictive-audiences-google-ads.html), and match ad variations to results when you run [predictive creative testing](/articles/predictive-creative-testing-ai-ad-creatives.html). ## Keep reading - [GA4 predictive audiences: how to use them in Google Ads](/articles/ga4-predictive-audiences-google-ads.html) - [Predictive creative testing: how to test AI ad creatives before you spend](/articles/predictive-creative-testing-ai-ad-creatives.html) - [Pre-deploy check skill for coding agents](/resources/pre-deploy-check-skill.html) ## FAQ ### What are UTM parameters? UTM parameters are tags added to a link, such as utm_source, utm_medium and utm_campaign, that tell Google Analytics where a visit came from. ### Are UTM parameters case sensitive in GA4? Yes. Google says values with different capitalization, such as Meta and meta, are treated as different values, so use lowercase as a standard. ### Should I use UTMs on Google Ads links? Use auto-tagging for Google Ads instead. It adds a gclid to ad clicks, and in GA4 auto-tagging takes priority over manual UTM tags with no override option. ### Where do I see UTM data in GA4? In the Acquisition > Traffic acquisition report, as session source, session medium, session source/medium and session campaign. --- # What is AGENTS.md? How to write one your coding agents follow URL: https://codema.ai/articles/what-is-agents-md-how-to-write-one.html Language: en Published: 2026-10-21 Description: AGENTS.md is a Markdown file that tells AI coding agents how to work on your repo. What it is, which tools read it, and how to write one that works. Every coding agent starts a session knowing nothing about your project. It doesn't know your test command, your folder layout or the one directory it must never touch. You can repeat all of that in every chat, or you can write it down once in an AGENTS.md file. AGENTS.md is a plain Markdown file at the root of your repository that tells AI coding agents how to work on your project. The [official site](https://agents.md/) calls it "a README for agents" and says it is used by over 60,000 open-source projects. This guide covers what AGENTS.md is, which tools read it, how to write one that agents actually follow, and how it relates to CLAUDE.md and Cursor rules. ## What is AGENTS.md? AGENTS.md is an open format, not a product feature. There are no required fields: it is standard Markdown, and you can use any headings you like ([agents.md](https://agents.md/)). The format grew out of work across the coding-agent ecosystem, including OpenAI Codex, Amp, Google's Jules, Cursor and Factory, and it is now stewarded by the Agentic AI Foundation under the Linux Foundation. The idea is simple. Your README is written for humans. AGENTS.md holds the extra detail an agent needs to do useful work without asking: the exact commands, the conventions, and the rules that are easy to break. ## Which tools read AGENTS.md Support is broad, but each tool loads the file a little differently. These details come from each vendor's own docs: | Tool | How it uses AGENTS.md | | --- | --- | | **Codex** | Reads AGENTS.md before doing any work. It also reads a global `~/.codex/AGENTS.md`, and an `AGENTS.override.md` takes priority over AGENTS.md in the same folder ([Codex docs](https://developers.openai.com/codex/guides/agents-md)). | | **Cursor** | Treats AGENTS.md as a simple alternative to `.cursor/rules`. Nested AGENTS.md files in subfolders are combined with their parents, and the more specific one takes precedence ([Cursor rules docs](https://cursor.com/docs/context/rules)). | | **Claude Code** | Reads AGENTS.md as project instructions when the project has no CLAUDE.md. If you also keep a CLAUDE.md, import AGENTS.md from it ([Claude Code memory docs](https://code.claude.com/docs/en/memory)). | | **Others** | The [agents.md](https://agents.md/) site lists many more agents that read the format, including GitHub Copilot's coding agent, Gemini CLI, Jules and Windsurf. | ## How to write an AGENTS.md file Start small and specific. The agents.md site suggests covering a project overview, build and test commands, code style, testing instructions, security considerations and pull request guidelines. Here is a starting point for a Next.js and Supabase app: ```markdown # AGENTS.md ## Project Client portal built with Next.js (App Router) and Supabase. Users sign in and manage their own records. ## Commands - Install: `npm install` - Dev server: `npm run dev` - Build: `npm run build` - Tests: `npm test` - Lint: `npm run lint` ## Code style - TypeScript strict mode. No `any` without a comment explaining why. - Server code reads data with the server client in `lib/supabase/server.ts`. ## Security rules - Never commit secrets. Only the Supabase publishable key may use a `NEXT_PUBLIC_` prefix. - Every new table gets Row Level Security and one policy per operation. - Do not edit files in `supabase/migrations/` that are already applied. Add a new migration instead. ## Definition of done - Build, tests and lint pass, and you paste the output. - New behavior has a test. ## Pull requests - One feature or fix per branch. - PR description lists every changed file and why. ``` A few habits make the difference between a file agents follow and one they skim: - **Be concrete enough to check.** Claude Code's docs give the pattern: "Run `npm test` before committing" works better than "Test your changes" ([Claude Code memory docs](https://code.claude.com/docs/en/memory)). - **List the real commands.** Agents will run test commands they find in AGENTS.md and try to fix failures before finishing, according to the agents.md FAQ. Make sure the commands exist in `package.json`. - **Keep it short.** Claude Code recommends under 200 lines per instruction file, because longer files use more context and reduce adherence. Codex stops adding instruction files once their combined size reaches 32 KiB by default ([Codex docs](https://developers.openai.com/codex/guides/agents-md)). - **Write rules, not essays.** Bullets under clear headings are easier to follow than paragraphs. - **Treat it as living documentation.** When an agent makes the same mistake twice, add a line. You don't have to start from a blank page. Codex's `/init` command creates an AGENTS.md for the project ([Codex CLI](https://developers.openai.com/codex/cli)), and our [AGENTS.md starter template](/resources/agents-md-starter-template.html) is a fuller version of the example above. ## Nested AGENTS.md files for monorepos In a repo with several packages, put one AGENTS.md at the root and another inside each package. According to agents.md, "the closest one takes precedence", so each subproject can ship its own commands and rules. If instructions conflict, the closest AGENTS.md to the edited file wins, and explicit instructions in your chat override everything. Codex documents its exact order: it walks from the project root down to your working directory, includes at most one file per folder, and joins them so files closer to your current directory appear later and override earlier guidance ([Codex docs](https://developers.openai.com/codex/guides/agents-md)). ## AGENTS.md vs CLAUDE.md vs Cursor rules These files overlap, so it helps to know when each one loads: - **AGENTS.md** is the shared, tool-neutral file. Put anything every agent should know here. - **CLAUDE.md** is Claude Code's own instruction file. By default, Claude Code reads AGENTS.md only when there is no CLAUDE.md or CLAUDE.local.md in your working directory or above it. If you need both, add a line with `@AGENTS.md` at the top of CLAUDE.md so Claude Code imports the shared file, then add Claude-specific notes below it ([Claude Code memory docs](https://code.claude.com/docs/en/memory)). - **Cursor project rules** live in `.cursor/rules/` as `.mdc` files with `description`, `globs` and `alwaysApply` front matter. A plain `.md` file in that folder is ignored. Use rules when an instruction should only load for certain files, and keep each rule under 500 lines ([Cursor rules docs](https://cursor.com/docs/context/rules)). If you only need one set of rules, AGENTS.md is enough: our [universal AGENTS.md starter](/resources/agents-md-starter-template.html) includes bridge files for Claude Code and Gemini CLI. The simplest setup for most teams is one AGENTS.md as the source of truth, plus a one-line CLAUDE.md that imports it if anyone uses Claude Code alongside other tools. ## What not to put in AGENTS.md - **Secrets.** AGENTS.md is committed to Git and read by every agent. Name environment variables, never their values. - **Long procedures that only matter sometimes.** A ten-step release process belongs in an [agent skill](/articles/what-are-agent-skills-write-your-first-skill.html), which loads only when the task calls for it. - **Things a hook should enforce.** Instruction files are context, not enforcement. Claude Code's docs say that to block an action regardless of what the agent decides, you should use a hook or a permission rule instead ([Claude Code memory docs](https://code.claude.com/docs/en/memory)). Our guide to [running coding agents safely](/articles/run-coding-agents-safely-permissions-sandboxes.html) covers those controls. ## Keep reading - [Cursor vs Claude Code vs Codex: how to pick an AI coding agent](/articles/picking-a-coding-agent-cursor-claude-code-codex.html) - [10 copy-paste AI coding prompts to ship a web app](/articles/10-copy-paste-prompts-ship-web-app-with-ai.html) - [AGENTS.md starter template for Next.js and Supabase](/resources/agents-md-starter-template.html) ## FAQ ### What is AGENTS.md? AGENTS.md is a plain Markdown file in your repository that gives AI coding agents the context and instructions they need, such as build commands, code style and security rules. It has no required fields. ### Does Claude Code read AGENTS.md? Yes. Claude Code reads AGENTS.md as project instructions when there is no CLAUDE.md or CLAUDE.local.md in the working directory or above it. Otherwise, import it from CLAUDE.md with a line containing @AGENTS.md. ### Where should AGENTS.md go? Put AGENTS.md at the root of your repository. In a monorepo, add another one inside each package; agents use the closest file to the code they are editing. ### What is the difference between AGENTS.md and Cursor rules? AGENTS.md is a tool-neutral Markdown file every agent can read. Cursor project rules are .mdc files in .cursor/rules with description, globs and alwaysApply front matter, which control when each rule loads in Cursor. ---