How to buildOctober 12, 202611 min read
Vibe coding: from prototype to productStep 1 of 7

AI assistants in development: Claude Code and Codex in practice

In short

Claude Code and Codex are agentic tools: they read the repository, edit files and run commands on their own instead of completing a single line. To make an agent helpful rather than harmful you need three things: a project instruction file (AGENTS.md or CLAUDE.md) with commands and restrictions, permissions and a sandbox that technically limit what it can do, and a task with verifiable acceptance criteria. The agent's output goes through the same tests and review as human code.

How-toLevel: IntermediateAI-Assisted CodingPractice: ~30–60 min

After this you will be able to

  • write an AGENTS.md instruction file for your project and load it in Claude Code through CLAUDE.md
  • configure Claude Code permissions in .claude/settings.json and the Codex sandbox in .codex/config.toml, then check them with doctor
  • give an agent a task with context, acceptance criteria and a verification command
  • review an agent's changes with a checklist: diff scope, tests, secrets, dependencies and licenses

Verified with

Claude Code 2.1.296Codex CLI 0.162.1markdownlint-cli2 0.23.3Node.js 24 LTS (24.18)

Checked against docs: October 12, 2026

Contents
  1. 01An agent, not autocomplete
  2. 02Installation and first run
  3. 03Instruction files: AGENTS.md and CLAUDE.md
  4. 04Permissions and sandboxing
  5. 05How to write a task
  6. 06The workflow: plan → changes → tests → review
  7. 07Reviewing agent code and where not to trust it

An agent, not autocomplete

Autocomplete suggests the next line in your editor, and a person decides at every step. An agentic tool takes the whole task: it finds the relevant files, plans, edits several files, runs tests and terminal commands, reads the errors and fixes them. That is how Claude Code from Anthropic and Codex from OpenAI work — in the terminal, in IDE extensions, in desktop apps and in the cloud.

The cost of a mistake grows with the capabilities. A bad autocomplete suggestion is one line you can see. An agent can change twenty files, install a package, run a migration or read a file with keys. So working with an agent rests on three pillars: project instructions, technical limits and a verifiable result.

Autocomplete

  • A suggestion in the current file
  • A person accepts every line
  • Does not run commands
  • Context is the open file and its neighbours

Agent: Claude Code, Codex

  • A whole task across several files
  • Acts on its own within its permissions
  • Runs tests, builds, git and other tools
  • Finds the context it needs in the repository

Installation and first run

Both tools install with a single command. For Claude Code the documentation recommends the native installer; Homebrew, WinGet and an npm package are also available, and the npm package needs Node.js 22 or later. Codex CLI installs with a standalone installer from chatgpt.com, via npm or Homebrew. You also need an account: on first launch Claude Code asks you to sign in with a Claude subscription or an Anthropic Console account, and Codex with ChatGPT or another available sign-in method.

bash
# Claude Code: native installer (macOS, Linux, WSL)
curl -fsSL https://claude.ai/install.sh | bash

# Codex CLI: standalone installer (macOS, Linux)
curl -fsSL https://chatgpt.com/codex/install.sh | sh

# Alternative for both: global npm packages
npm install -g @anthropic-ai/claude-code
npm install -g @openai/codex
Commands from the official documentation. On Windows, use the PowerShell installers documented there
terminal
$ claude --version
2.1.296 (Claude Code)
$ codex --version
codex-cli 0.162.1
Checking the installation; these are the versions the examples in this article were checked on

Start the agent from the repository root with claude or codex. The working directory determines both which instruction files it reads and the boundary within which it may write. Before a task, commit the current state or create a branch: the Codex documentation recommends Git checkpoints before and after a task so you can revert the changes.

Instruction files: AGENTS.md and CLAUDE.md

Every agent session starts with a clean context. What you would otherwise explain every time goes into a project instruction file. Codex reads AGENTS.md: first the global one in ~/.codex, then the files from the project root down to the current directory; the one closest to the working directory is read last and refines the general rules. The combined size is capped at 32 KiB by default (project_doc_max_bytes). AGENTS.md is an open format that other agents support too; it is described at agents.md.

Claude Code reads CLAUDE.md in the project, ~/.claude/CLAUDE.md with personal rules and CLAUDE.local.md with settings that stay out of git. If a project has only AGENTS.md, recent Claude Code versions read it directly, but when a CLAUDE.md exists, they read only that. A reliable way to keep one source of rules for both tools is a shared AGENTS.md plus a short CLAUDE.md that imports it with an @AGENTS.md line. You can get a first draft with /init: Claude Code analyses the project and proposes commands and conventions.

Build, test and lint commands the agent cannot guess

Leave out
Anything the agent can learn by reading the code

Code rules that differ from common conventions

Leave out
Generic advice like “write clean code”

Where things live and the project's architectural decisions

Leave out
A description of every file

Restrictions: secrets, applied migrations, deployment, git push

Leave out
Detailed API documentation — link to it instead

The definition of done

Leave out
Information that changes often
What to put in the instruction file — following the Claude Code documentation
AGENTS.md
# AGENTS.md

## Project

- Online booking for a beauty salon: Next.js (App Router), TypeScript,
  PostgreSQL via Prisma.
- Application code is in `src/`, tests are in `tests/`,
  migrations are in `prisma/migrations/`.

## Commands

- Install dependencies: `npm ci`
- Type check: `npm run typecheck`
- Lint: `npm run lint`
- All tests: `npm test`
- One test file: `npm test -- tests/bookings.test.ts`

## Conventions

- TypeScript strict mode; no `any` in new code.
- Validate every external input with `zod` at the boundary
  (`src/schemas/`).
- Database access only through `src/db/`;
  never build SQL by string concatenation.
- New UI strings go to both `messages/ru.json` and `messages/en.json`.

## Workflow

- For changes that touch more than one file, propose a plan first
  and wait for confirmation.
- After changes, run type check, lint and the related tests,
  and show the output.
- Keep the diff limited to the task: no unrelated refactoring or reformatting.
- Ask before adding a production dependency.

## Security

- Never read, print or commit `.env` files, keys or tokens.
  If a new variable is needed, name it in the summary
  and leave the value to a human.
- Do not edit applied migrations in `prisma/migrations/`;
  create a new migration instead.
- Never run `git push`, deployments or commands
  against production databases.

## Definition of done

- Type check, lint and tests pass.
- New behavior is covered by a test.
- The summary lists what changed, how it was verified
  and what is still uncertain.
A template for a Next.js and Prisma project: replace the commands and paths with your own. Checked with markdownlint-cli2
CLAUDE.md
# CLAUDE.md

@AGENTS.md

## Claude Code

- Use plan mode for any change under `src/payments/`.
- Before reporting a task as done, review the diff
  against the acceptance criteria of the task.
CLAUDE.md imports the shared rules and adds what applies to Claude Code only

Keep the file short. The Claude Code documentation recommends under 200 lines per file and asking of every line whether the agent would make a mistake without it: a long file consumes context, and important rules get lost in it. A good reason to add a line is the agent repeating the same mistake twice, or a review catching something it should have known. Rules for only part of the code go into a nested AGENTS.md (Codex) or into .claude/rules/ scoped to paths (Claude Code).

Permissions and sandboxing

This is where the real boundary is. A Claude Code permission mode defines what the agent does without asking. Since version 2.1.283, interactive sessions in the terminal and VS Code start in auto mode by default: a separate classifier model reviews actions and blocks risky ones. You change the mode with the --permission-mode flag, with Shift+Tab in a session or with the permissions.defaultMode setting.

plan

What it does without asking
Reads files and runs read-only commands
When it fits
Exploration, unfamiliar code, a plan before changes

manual (default in settings)

What it does without asking
Reads only; edits and commands need approval
When it fits
Sensitive repositories, first sessions

acceptEdits

What it does without asking
Edits files and runs simple file commands in the working directory
When it fits
A clear task, you review the diff at the end

auto

What it does without asking
A classifier reviews actions and blocks risky ones
When it fits
Long tasks with configured rules

dontAsk

What it does without asking
Only what is pre-approved; everything else is silently denied
When it fits
Scripts and CI with a narrow set of commands

bypassPermissions

What it does without asking
Everything except the few actions no mode approves
When it fits
Only a container or VM where the agent cannot break anything

On top of the mode, allow, ask and deny rules in .claude/settings.json apply. They are evaluated deny first, then ask, then allow: a broad deny cannot be bypassed by a narrower allow, and deny rules hold in every mode. Commit the project file so the whole team gets the rules; personal exceptions go into .claude/settings.local.json.

.claude/settings.json
{
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
  "permissions": {
    "allow": [
      "Bash(npm run typecheck)",
      "Bash(npm run lint)",
      "Bash(npm test *)"
    ],
    "ask": [
      "Bash(git push *)",
      "Bash(npm install *)"
    ],
    "deny": [
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(./secrets/**)",
      "Bash(npx prisma migrate deploy *)"
    ],
    "disableBypassPermissionsMode": "disable"
  }
}
Checks run without asking, git push and package installs need approval, secrets and production migrations are denied. disableBypassPermissionsMode turns off the no-checks mode

An important caveat from the documentation: Read and Bash rules are not an absolute guarantee. A Read(./.env) deny applies to the built-in tools and recognised commands such as cat, but not to a Node.js or Python script that opens the file itself; a Bash(curl *) rule does not stop sh -c 'curl …'. OS-level enforcement comes from the sandbox (/sandbox), and the most reliable option is not to keep production secrets in the working copy at all.

Codex separates two layers. The sandbox_mode defines what the agent can technically do: read-only, workspace-write or danger-full-access. The approval_policy defines when it must ask: on-request or never. In the Auto preset (workspace-write with on-request) Codex writes only inside the working directory, network access for commands is off, .git and .codex are write-protected, and it asks before going beyond those limits. The --dangerously-bypass-approvals-and-sandbox flag (alias --yolo) turns off both the sandbox and the prompts — the documentation reserves it for externally isolated environments.

.codex/config.toml
# Project config: Codex loads it only after you mark the project as trusted
sandbox_mode = "workspace-write"
approval_policy = "on-request"

[sandbox_workspace_write]
network_access = false
Project settings pinned explicitly. Personal settings live in ~/.codex/config.toml

Make sure the settings are understood the way you intended. Both tools have a doctor command that parses the configuration without starting a session or calling a model.

terminal
$ codex doctor
  ✓ config       loaded
      config.toml parse        ok
  ✓ sandbox      restricted fs + restricted network · approval OnRequest

$ claude doctor
Invalid settings
- .claude/settings.json › permissions.defaultMode: Invalid value. Expected one of: "acceptEdits", "auto", "bypassPermissions", "default", "dontAsk", "plan"
Fragments of real output with shortened paths: Codex with the config above and Claude Code with a deliberate typo in the mode. With a valid settings.json there is no Invalid settings section

How to write a task

An agent stops when the work “looks done”. If the task has no check the agent can run itself, you become the check. A good task answers four questions: where to look (files, modules, the related issue), what the result is (behaviour, not “improve it”), how to verify it (a test, a command, an expected response) and what not to touch.

TASK.md
# Task: limit booking attempts per phone number

## Context

- The booking handler is `src/app/api/bookings/route.ts`.
- A rate limit helper already exists in `src/lib/rate-limit.ts`; reuse it.
- Tests for bookings are in `tests/bookings.test.ts`.

## Goal

Reject more than 3 booking requests from the same phone number
within 10 minutes.

## Acceptance criteria

- [ ] The 4th request for the same phone within 10 minutes returns HTTP 429
  with the body `{ "error": "too_many_requests" }`.
- [ ] Requests for other phone numbers are not affected.
- [ ] The limit resets after 10 minutes; the test uses fake timers,
  not real waiting.
- [ ] No new dependencies and no changes outside `src/app/api/bookings/`,
  `src/lib/` and `tests/`.

## Verification

Run `npm run typecheck`, `npm run lint`
and `npm test -- tests/bookings.test.ts`, then show the output.

## Out of scope

- UI changes.
- Database schema changes.

## How to work

1. Read the files above and propose a plan. Wait for my confirmation.
2. Write a failing test first, then the implementation.
3. Summarize the diff and list anything you were unsure about.
A sample task with acceptance criteria: paste it into the session, or save it as a file and refer to it
  • Write criteria as verifiable facts — a status code, a body, an edge case — not “works correctly”.
  • Name existing code to reuse, otherwise the agent may write its own copy.
  • Limit the scope: a list of folders and an “out of scope” section protect against drive-by refactoring.
  • Ask to see the output of the checks rather than the phrase “tests pass”: reviewing output is faster.
  • One session, one task. The Claude Code documentation recommends clearing the context with /clear between unrelated tasks and, after two failed corrections, starting over with a better initial prompt.

The workflow: plan → changes → tests → review

PlanChangesTestsReviewPull request
Each stage ends with something you can check: a plan, a diff, test output, review findings
  1. Plan

    Switch to plan mode in Claude Code or to read-only in Codex (the /permissions command). The agent reads the code and proposes which files to change. Fix the plan before any code appears: redoing a plan is cheaper than redoing a diff. An edit you can describe in one sentence does not need a plan.

  2. Changes

    Switch to a working mode and ask for the plan to be implemented, starting with a failing test. Work on a separate branch and keep parallel tasks in separate worktrees.

  3. Tests

    The agent runs the type check, linter and tests from AGENTS.md and fixes errors until the checks pass. Require it to fix the cause, not to disable the check or the test.

  4. Review

    Automated first: in Codex, /review checks uncommitted changes or a branch against its base; in Claude Code, the built-in /code-review or a subagent compares the diff with the task's criteria. Then your own review with the checklist below.

  5. Pull request

    An agent's changes take the same path as human code: a pull request, CI, a colleague's review, a protected branch.

Reviewing agent code and where not to trust it

Generated code looks confident whether or not it is correct. Read the whole diff, not just the agent's final summary: the summary describes the intent, the diff shows the result.

  • The diff is limited to the task: no edits to unrelated files, no drive-by formatting, no deleted tests
  • Tests check the behaviour from the criteria rather than mirroring the implementation; no skipped or weakened assertions
  • Checks were run, their output is shown, CI is green
  • No secrets in code, logs, test data or commit messages
  • New dependencies are really needed, exist under that exact name, are maintained, and their license is compatible with the project
  • External input is validated, SQL is parameterised, HTML output is escaped, permissions are checked on the server
  • New migrations do not change already applied files
  • Errors are not silently swallowed

Security: sign-in, permissions, payments, cryptography

Risk
Plausible code with a hole: permission checks only on the client, home-made hashing
What to do
Review by someone who knows the area, tests for the failure cases, a check against OWASP

Secrets

Risk
A key in a prompt, a log or a test file; the agent read .env
What to do
Read denies, secrets outside the working copy, a secret scanner in CI

Licenses and dependencies

Risk
A package with an incompatible license or a look-alike name owned by someone else
What to do
Check the registry, repository and license of every new package

Untrusted content

Risk
Instructions in a README, an issue or a web page change the agent's behaviour — prompt injection
What to do
Do not give the agent broad permissions while it handles third-party content; network by allowlist

Architecture and an unfamiliar domain

Risk
A locally reasonable solution contradicts how the system works or the business rules
What to do
A person makes the decision; the agent implements and explores
Where not to take the assistant's word for it

With architecture and an unfamiliar domain the problem is not syntax but missing context: the agent does not know agreements that are not in the code and will not ask about them unless you tell it to. If you cannot assess the result yourself, the agent does not take the responsibility for checking it off your hands. The Claude Code documentation puts it bluntly: if you cannot verify it, do not ship it.

How this was verified4 · passed1 · not runchecked 12 October 2026

“Run” means the code was executed in a scratch project or container and the output in the article comes from that run. “Partial” means it was checked against stubs instead of external services. “Not run” means it needs a device, an account or a key; the steps were checked against the official documentation. The verification project files and run logs are kept in the InterLAB archive.

Tell us about your task — we'll review your request and get back to you

Got a project?
We'll scope and estimate it — for free.

Tell us about the product or the problem. After reviewing the task we'll come back with an architecture, a timeline and a price for the first version.

  • Scope and risks estimated before we start
  • NDA — yours or ours
  • Work starts within a week

Please do not send passwords, access keys or source code through this form — we will agree a safe way to share access separately.

By clicking the button you agree to the processing of your personal data.