Appearance
Your Vibe Coding Toolkit
The scenarios in the previous lesson are real. Here is how you make them happen on your own machine. Claude Code is the tool you will use for most of the vibe coding in this course. The difference between using it casually and using it well comes down to five specific habits: giving it persistent memory of your project, scripting repeatable commands, feeding it real file context, knowing when to let it run unattended, and always having an undo button ready. Five short labs, one habit each.
What you'll learn
- Persistent project memory via
CLAUDE.md, loaded automatically every session - Building custom slash commands to script repetitive workflows
--dangerously-skip-permissionsfor batch tasks, kept deliberate and scoped- Git as the undo button for every AI-driven change
The CLI landscape
Before the labs, a quick lay of the land. The course uses Claude Code because it is the most widely adopted agentic coding CLI, but the five habits below apply to any AI terminal tool. If you prefer OpenCode, Gemini CLI, or Aider, the specific commands differ but the workflow is the same: persistent context, reusable commands, real file input, and a deliberate relationship with auto-approve mode.
This lesson covers Claude Code specifically. For a deeper reference, see the Claude Code course which goes into skills, hooks, subagents, and CI/CD integration, or the Terminal Agents course which compares OpenCode, Aider, OpenHands, and Goose side by side.
Lab 1: Persistent Project Context with CLAUDE.md
Stop repeating setup instructions in every chat. A
CLAUDE.mdfile at your project root holds permanent rules, conventions, and environment details. Claude Code reads it automatically at the start of every session.
Goal
Give Claude Code a clear picture of your project so it never needs to ask "what Python version?" or "where is the database?" again.
Step-by-Step
1. Install Claude Code:
bash
npm install -g @anthropic-ai/claude-codeVerify it is available:
bash
claude --version2. Create your CLAUDE.md:
bash
cd ~/projects/my-agent-projectCreate CLAUDE.md at the project root with your stack and conventions:
markdown
# Project Context
## Environment
- Python 3.12 with uv for package management
- PostgreSQL on localhost:5432
- Node.js 20 LTS via NVM
## Conventions
- Use async Python with asyncio wherever possible
- Validate all data with Pydantic v2
- Never leave TODO placeholders -- write real implementations
- Environment variables in `.env`, never committed3. Verify it loaded:
Start Claude Code and ask it what it knows about your project:
bash
claude
> What does my project use for Python and database?Claude Code should reference the details from your CLAUDE.md without you repeating them. If it does not, check that CLAUDE.md is in the directory you launched claude from, it reads from the current working directory upward.
Lab 2: Custom Slash Commands
Package a complex, multi-line prompt you use often, a security audit, a test-writing pass, a schema generator, into an instant, reusable custom slash command instead of retyping it every time.
Goal
Create a custom slash command /agent:new that takes a name as an argument and generates a boilerplate async FastAPI agent script.
Step-by-Step
1. Create the commands directory:
bash
mkdir -p .claude/commands2. Create the command file:
Create .claude/commands/agent-new.md:
markdown
---
description: Generate a boilerplate async FastAPI agent
argument-hint: AgentName
---
Write a fully implemented, production-grade async Python FastAPI agent.
Specifications:
- The agent class name must be: $ARGUMENTS
- Use Pydantic v2 for request validation
- Include a mock cognitive loop using asyncio.sleep()
- Use Python's standard logging library
- Save to `agents/$ARGUMENTS.py`The $ARGUMENTS placeholder receives whatever text you type after the command name.
3. Run it:
bash
claude
> /agent-new WorkflowOrchestratorClaude Code parses the command file, substitutes the argument, and generates the agent. The file lands in agents/WorkflowOrchestrator.py.
Custom commands can have frontmatter for metadata (description, argument-hint, allowed-tools, model) and a markdown body for the prompt. The ! backtick syntax lets you inline shell output. The @ syntax injects file contents. Both are covered in the next lab.
Lab 3: File Injection and Shell Passthrough
Never let the model guess at file contents. Use
@to inject a real file into the prompt, and!to run a system command without leaving the REPL.
Goal
Perform a security and performance audit on your generated agent file using explicit file context and direct terminal feedback.
Step-by-Step
1. Inject a file into the prompt:
bash
claude
> Audit this file for async race conditions, missing error handling, and performance issues: @agents/WorkflowOrchestrator.pyThe @ symbol followed by a file path reads the file and includes its full contents in the prompt. Claude Code sees the actual code, not your description of it.
2. Review the diff:
Claude Code shows proposed changes as a diff before applying them. Read through it, approve what looks right, ask for revisions on what does not.
3. Run shell commands without leaving the session:
bash
> !pytest -v agents/The ! prefix runs a shell command and pipes the output back into your chat. You can also use backtick syntax in custom commands and CLAUDE.md:
markdown
Current git branch: !`git branch --show-current`This keeps your context current without manual updates.
Lab 4: Batch Execution with Auto-Approve
--dangerously-skip-permissionsskips the per-action confirmation prompt. It is what makes large batch tasks fast, and what makes it genuinely risky on a filesystem you care about. Use it deliberately, not as a default.
Goal
Write an autonomous helper tool that scans all .py files for hardcoded secrets and flags them, running in auto-approve mode to skip confirmation on every file write.
Step-by-Step
1. Commit or stash your current work:
bash
git add -A && git commit -m "checkpoint before auto-approve batch"This is your undo button. If the batch run does something you did not intend, git reset --hard HEAD~1 reverts everything.
2. Launch with auto-approve:
bash
claude --dangerously-skip-permissionsThe terminal shows a warning that confirmations are disabled. This is not a default, it is a deliberate mode you opt into.
3. Run the batch task:
> Create a python script 'tools/secret_scanner.py' that recursively searches the current directory for hardcoded API keys, passwords, or tokens using regex. Then execute it and show the results.Because auto-approve is active, Claude Code writes the scanner, runs it, and returns results without pausing for confirmation on each step.
4. Return to normal mode:
Exit the session and restart without the flag. Auto-approve should not be your default, it is a tool you reach for when you have a clear, scoped batch task and a git commit behind you.
Lab 5: Git as Your Safety Net
Auto-approve mode and multi-file refactors both carry risk. The undo button is git, and the habit is committing before anything you are not certain about.
Goal
Start an auto-approve session, make a deliberately destructive change, and recover using git.
Step-by-Step
1. Checkpoint with git:
bash
git add -A && git commit -m "checkpoint"2. Make a destructive change:
bash
claude --dangerously-skip-permissions
> Delete all comments and docstrings in tools/secret_scanner.py and rename every variable to single characters.3. Inspect the damage:
bash
cat tools/secret_scanner.pyThe file is broken and unreadable. Good. This is why step 1 exists.
4. Revert:
bash
git checkout -- tools/secret_scanner.pyOr if there were multiple files:
bash
git reset --hard HEADThe file is back to its pre-change state.
The habit to build: git commit before any auto-approve session, any multi-file refactor, any prompt where the words "delete," "rename all," or "refactor every" appear. One command, zero drama.
What goes wrong
| Mistake | How you notice it | The fix |
|---|---|---|
| Repeating the same setup context in every prompt | You are retyping your stack and conventions constantly, and the model still sometimes forgets them mid-session | Put it in CLAUDE.md once, it loads automatically every session |
| Running auto-approve as a default habit | An unattended edit does something you did not intend, with no confirmation step to catch it | Restart without --dangerously-skip-permissions. Reserve the flag for batch tasks you have thought through |
| Refactoring without a git commit behind you | A broken multi-file edit has no clean way back | git commit before any refactor you are not certain about. Two seconds of typing saves an hour of recovery |
| Asking the model to reason about a file it has not actually seen | Confidently wrong suggestions about code that does not match what is really on disk | Inject the real file with @path/to/file instead of describing it from memory |
| Custom command has a typo in the argument placeholder | $ARGUMENTS appears literally in the output instead of being replaced | Check your command file: the placeholder is $ARGUMENTS (all caps, with S). Claude Code also supports $1, $2 for positional args |
Confirm it worked
Open Claude Code and ask: "What does my project use for Python and database?" If the answer matches what you put in CLAUDE.md, Lab 1 is working. Run /agent-new TestAgent and confirm the file lands in agents/TestAgent.py, not somewhere unexpected. Inject a file with @path/to/file and confirm Claude Code references real function names from the file, not guesses. Run a one-line batch task with --dangerously-skip-permissions (after a git commit) and confirm it completes without pausing. Then git reset --hard HEAD and confirm the file reverts. If all five check out, you are using Claude Code as a tool, not a chatbot.
Next: Prompting & Context Engineering -- the craft underneath every prompt you wrote in these labs.