Master Claude Code's Power Features
Configure Claude Code with persistent memory, custom skills, and hooks.
Introduction
30 Second Summary
Every time you start a new session with an AI coding assistant, you lose all the context from last time. Your preferences, your project conventions, your shortcuts. It is like training a new colleague from scratch every single morning.
In this project, you will configure Claude Code's power features so it remembers your coding standards, packages multi-step workflows into single commands, auto-formats your code after every edit, and picks up exactly where you left off across sessions.
What You'll Build
You will configure Claude Code's advanced features while building a small Python CLI tool as your working codebase.
By the end of this project, you'll have:
- A CLAUDE.md project memory file that gives Claude persistent coding standards, plus a custom skill that packages test-and-commit into a single command.
- A PostToolUse hook that auto-formats Python files after every edit, and hands-on experience delegating tasks to subagents that keep your main context clean.
- Practice with session management to name, resume, and continue multi-step work across separate sittings.
- Secret Mission: create a custom subagent definition file that reviews your code for security issues.
Are there any prerequisites?
You should already have Claude Code installed, authenticated, and working. You also need Git installed. Basic familiarity with starting Claude Code sessions and giving prompts is enough to get started.
Set Up Your Project and CLAUDE.md
Every Claude Code session starts fresh with no memory of your preferences or project rules. CLAUDE.md solves this by giving Claude persistent project memory that loads automatically at the start of every session.
In this step, you will create your project folder, initialize a Git repository, and configure a CLAUDE.md file with coding standards that Claude follows every time you work on this project.
In this step, get ready to:
- Create a project directory with Git and a starter Python file.
- Generate and customize a CLAUDE.md with your coding standards.
- Verify Claude follows your standards when writing code.
Create your project structure
Before Claude Code can help you, it needs a project to work in. You will create a folder, initialize Git (which Claude Code relies on for tracking changes), and add a minimal Python file.
- Move to your Desktop by running this command in your terminal:
cd ~/Desktop
- Create your project folder and move into it by running these commands:
mkdir claude-power-features
cd claude-power-features
- Initialize a Git repository by running:
git init
Why does Claude Code need Git?
Claude Code uses Git to track every change it makes to your files. This gives you a safety net to review, undo, or compare edits Claude has made.
- Confirm the folder was created and Git initialized by running:
ls -a
You should see a .git folder in the output.
Now you need a Python file for Claude to work with. You will create a minimal cli.py that serves as the starting codebase.
- Open your text editor by pressing Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
- Type VS Code or Cursor and press Enter to open it.
- Click File in the top menu bar.
- Click Open Folder.
- Select the claude-power-features folder on your Desktop, then click Open.
- Create a new file by pressing Cmd+N (macOS) or Ctrl+N (Windows).
- Paste the following code into the new file:
# cli.py
if __name__ == "__main__":
print("Hello")
What does this code do?
This is a minimal Python script. The if __name__ == "__main__": block runs when you execute the file directly. It gives Claude something to build on in the next substeps.
- Save the file as cli.py by pressing Cmd+S (macOS) or Ctrl+S (Windows).
- In the save dialog, make sure you are inside the claude-power-features folder, then name the file cli.py.
Now start Claude Code inside your project.
- Switch back to your terminal (still inside the claude-power-features folder) and start Claude Code by running:
claude
You should see the Claude Code interactive session start with a prompt waiting for your input.
Claude Code not starting?
Make sure you are inside the claude-power-features folder. Run pwd (macOS/Linux) or cd (Windows) to check your current directory.
If you see a "command not found" error, Claude Code may not be installed. Help me troubleshoot why Claude Code won't start
Generate and customize CLAUDE.md
Claude Code's /init command analyzes your project and generates a starting CLAUDE.md file. You will customize it with specific coding standards for this project.
- In your Claude Code session, type the following command and press Enter:
/init
What does /init do?
Claude analyzes your codebase and creates a CLAUDE.md file with build commands, test instructions, and project conventions it discovers. If a CLAUDE.md already exists, /init suggests improvements rather than overwriting it.
Claude will generate a CLAUDE.md in your project root. Now you will replace its content with your specific coding standards.
- Switch to your text editor and open the CLAUDE.md file in the claude-power-features folder.
- Replace all of its content with the following:
# Project Memory
## Coding Standards
- Use Black for formatting with 88-character line length
- Always use f-strings for string interpolation
- All functions must have type hints and docstrings
## Commit Message Format
- Use conventional commits: feat:, fix:, docs:, chore:
- Keep subject line under 72 characters
## Testing Requirements
- Write pytest tests for all new functions
- Tests live in a `tests/` directory
What are these standards for?
Each section tells Claude how to behave when writing code for this project. Coding Standards controls formatting and style. Commit Message Format keeps your Git history clean. Testing Requirements ensures Claude writes tests alongside features.
- Save CLAUDE.md.
Now verify Claude loaded your memory file.
- Switch back to your Claude Code session and type:
/memory
You should see your CLAUDE.md listed among the loaded memory files.
CLAUDE.md not showing in /memory?
Make sure you saved the file as CLAUDE.md (with that exact name and capitalization) in the root of the claude-power-features folder, not inside a subfolder.
Help me figure out why Claude Code isn't loading my CLAUDE.md file
Test that CLAUDE.md is working
The real test of project memory is whether Claude actually follows your standards. You will ask Claude to add a function and check that it uses type hints, a docstring, and an f-string.
- In your Claude Code session, type this prompt and press Enter:
Add a greet function to cli.py that takes a name parameter and returns a greeting string. Update the main block to use it.
What should you look for?
Watch Claude's output. Because of your CLAUDE.md, the function should include a type hint (name: str), a return type annotation (-> str), a docstring, and use an f-string for the greeting.
- After Claude writes the code, open cli.py in your editor to confirm the function follows your standards.
Your cli.py should now look similar to this:
# cli.py
def greet(name: str) -> str:
"""Return a greeting string."""
return f"Hello, {name}!"
if __name__ == "__main__":
print(greet("World"))
Now test that Claude can save preferences to auto memory.
- In your Claude Code session, type this prompt and press Enter:
Remember that I always prefer f-strings for string interpolation in this project
Claude will save this preference to your project's auto memory.
- Verify the preference was saved by typing:
/memory
You should see the auto memory section now includes your f-string preference.
What is auto memory?
When you ask Claude to "remember" something, it stores that preference in a separate memory directory at ~/.claude/projects/<project>/memory/. These memories load automatically in future sessions alongside your CLAUDE.md.
Claude didn't follow the CLAUDE.md standards?
If the generated function is missing type hints or a docstring, try asking Claude again with a more explicit prompt like "rewrite the greet function following the CLAUDE.md standards." Claude occasionally needs a nudge on the first interaction after generating CLAUDE.md.
Help me understand why Claude isn't following my CLAUDE.md coding standards
✔️ Awesome, I've got everything!
Great work. Make sure you have saved both CLAUDE.md and cli.py.
ⓧ I'd like to double check the full code
Here is what your two files should look like at this point.
# Project Memory
## Coding Standards
- Use Black for formatting with 88-character line length
- Always use f-strings for string interpolation
- All functions must have type hints and docstrings
## Commit Message Format
- Use conventional commits: feat:, fix:, docs:, chore:
- Keep subject line under 72 characters
## Testing Requirements
- Write pytest tests for all new functions
- Tests live in a `tests/` directory
# cli.py
def greet(name: str) -> str:
"""Return a greeting string."""
return f"Hello, {name}!"
if __name__ == "__main__":
print(greet("World"))
Your project now has persistent memory that loads every time you start Claude Code. Next up, you will create a custom skill that packages a multi-step workflow into a single command.
Create a Custom Skill
Your CLAUDE.md is loaded and Claude follows your coding standards on every response. But what about multi-step workflows you repeat over and over? Running tests, staging files, and committing code is a sequence you'll execute dozens of times per project.
Claude Code skills let you package these workflows into a single slash command defined in a markdown file. In this step, you'll create a /test-and-commit skill that runs your test suite and commits automatically when everything passes.
In this step, get ready to:
- Create a skill directory and SKILL.md file with YAML frontmatter and instructions.
- Test the skill by invoking it after a code change.
- Verify the skill persists across context compaction.
Create the skill directory and SKILL.md
Skills live in a specific folder structure inside your project. Claude Code looks for skill files at .claude/skills/<name>/SKILL.md and loads them as slash commands.
- Open a new terminal window alongside your Claude Code session.
- Create the skill directory by running this command:
mkdir -p .claude/skills/test-and-commit
- Confirm the directory exists by running:
ls .claude/skills/test-and-commit
You should see an empty directory listed with no errors.
- In your text editor, create a new file called SKILL.md inside the .claude/skills/test-and-commit/ directory.
- Paste the following content into SKILL.md:
---
description: Runs pytest and commits all staged changes with a conventional commit message.
disable-model-invocation: true
allowed-tools: Bash(python *) Bash(pytest *) Bash(git *)
---
# Test and Commit
1. Run `pytest` to execute all tests.
2. If all tests pass, stage all changes with `git add -A`.
3. Commit with the message: `feat: $ARGUMENTS`
4. If tests fail, report the failures and do not commit.
What does this file do?
The section between the --- lines is YAML frontmatter that configures how the skill behaves.
- `description` tells Claude when this skill is relevant and shows up in the slash command menu.
- `disable-model-invocation: true` prevents Claude from running this skill on its own. You control when it fires by typing the slash command manually.
- `allowed-tools` grants the skill permission to run specific shell commands (pytest and git) without asking you each time.
The markdown body below the frontmatter contains the instructions Claude follows when you invoke the skill. $ARGUMENTS gets replaced with whatever text you type after the slash command.
- Save SKILL.md.
File not showing up in the right place?
Make sure the file path is exactly .claude/skills/test-and-commit/SKILL.md relative to your project root (claude-power-features). The directory must be .claude with a leading dot.
Help me troubleshoot my SKILL.md file location
Test the skill
Your skill is defined, but you need a test suite and a code change to verify it works end-to-end. You'll ask Claude to add a function, then invoke the skill to test and commit in one shot.
- Switch back to your Claude Code session.
- Type this prompt to ask Claude to set up a test file and add a new function:
Create a tests/ directory with a test_cli.py file that tests the greet function. Then add a new function called "add" to cli.py that takes two integers and returns their sum. Add a test for it too.
What will Claude do?
Claude reads your CLAUDE.md standards and creates the test file with proper type hints and docstrings. It also adds the add function to cli.py following your coding conventions.
- After Claude finishes, invoke your new skill by typing this command in the Claude Code session:
/test-and-commit added new utility function
Claude runs pytest first. If all tests pass, it stages your changes and commits with the message feat: added new utility function.
What should I see?
You should see Claude execute pytest in the terminal output, report passing tests, then run git add -A followed by git commit. The commit message uses the conventional format from your CLAUDE.md.
- Verify the commit landed by asking Claude to run:
run git log --oneline -1
You should see a commit with the message feat: added new utility function at the top of the log.
Tests failing or skill not found?
- If the skill doesn't appear when you type /, check that the file is saved at the exact path .claude/skills/test-and-commit/SKILL.md.
- If pytest fails with a "module not found" error, ask Claude to install pytest first: install pytest with pip.
- If the commit fails, make sure you initialized git in your project folder during Step 1.
Help me debug my /test-and-commit skill
Verify skill persistence
Skills need to survive context compaction to be truly useful. When Claude's context window fills up, /compact summarizes the conversation to free space. After compaction, Claude Code re-attaches the most recent invocation of each skill so it remains available.
- In your Claude Code session, run the compact command by typing:
/compact
Claude summarizes your conversation history to free up context space.
- Type / and look for test-and-commit in the list of available commands.
- Invoke the skill one more time to confirm it still works by typing:
/test-and-commit verified skill persistence
Claude runs the same test-then-commit workflow. You should see another successful commit in your git history.
Why does the skill survive compaction?
Skills are stored as files on disk, not in conversation memory. After compaction, Claude Code re-reads your SKILL.md and re-attaches it to the session. This means your skills work reliably across long sessions, unlike instructions given only in chat.
Skill missing after compaction?
If the skill doesn't appear after /compact, confirm the SKILL.md file still exists on disk at .claude/skills/test-and-commit/SKILL.md. The file may have been accidentally deleted or moved.
Help me understand why my skill disappeared after compaction
✔️ Awesome, I've got everything!
Great. Double check you've saved your SKILL.md file and that your git log shows at least one commit from the skill.
ⓧ I'd like to double check the full code
Here is the full SKILL.md file:
---
description: Runs pytest and commits all staged changes with a conventional commit message.
disable-model-invocation: true
allowed-tools: Bash(python *) Bash(pytest *) Bash(git *)
---
# Test and Commit
1. Run `pytest` to execute all tests.
2. If all tests pass, stage all changes with `git add -A`.
3. Commit with the message: `feat: $ARGUMENTS`
4. If tests fail, report the failures and do not commit.
And here is your cli.py after Claude added the add function:
# cli.py
def greet(name: str) -> str:
"""Return a greeting string."""
return f"Hello, {name}!"
def add(a: int, b: int) -> int:
"""Return the sum of two integers."""
return a + b
if __name__ == "__main__":
print(greet("World"))
You now have a reusable slash command that packages a test-and-commit workflow into a single invocation. Next up, you'll automate file formatting with hooks so that every edit Claude makes is automatically cleaned up.
Set Up Auto-Formatting Hooks
Your CLAUDE.md sets coding standards and your skill packages a workflow into a single command. But both still rely on Claude choosing to follow them.
Hooks are different. They are shell commands that run automatically at specific points in Claude Code's lifecycle. In this step, you will create a hook that runs Black (Python's formatter) every time Claude edits a file. No prompting required.
In this step, get ready to:
- Create a PostToolUse hook configuration in .claude/settings.json.
- Install Black and test the hook by having Claude write poorly-formatted code.
- Verify the hook is registered with /hooks.
Create the hook configuration
Claude Code exposes lifecycle events that your hooks can listen to. The PostToolUse event fires after Claude finishes using a tool. By adding an Edit|Write matcher, your hook will only trigger after file-editing tools, not after every single tool call.
- Open .claude/settings.json in your text editor. If the file does not exist yet, create it inside the .claude folder in your project.
- Paste the following configuration into the file:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"command": "echo $CLAUDE_TOOL_OUTPUT | python -c \"import sys, json; data=json.load(sys.stdin); path=data.get('file_path',''); print(path)\" | xargs -I{} black {}"
}
]
}
}
What does this configuration do?
The PostToolUse event fires every time Claude finishes using a tool. The Edit|Write matcher narrows it down to only file-editing tools.
The command pipes $CLAUDE_TOOL_OUTPUT (the JSON result from the tool) into a Python one-liner that extracts the file_path field. That path then gets passed to black via xargs, which formats the file in place.
- Save .claude/settings.json.
Why Python instead of jq?
The official docs show jq for JSON parsing in hooks. On Windows with Git for Windows, jq may not be pre-installed. Since you already have Python, the one-liner works cross-platform without installing anything extra.
File not saving correctly?
Make sure the file is valid JSON. Trailing commas and comments are not allowed in JSON files. If you already had content in .claude/settings.json, merge the hooks key into your existing object rather than replacing the whole file.
Help me fix my .claude/settings.json file
Install Black and test the hook
The hook calls black on every edited file, so you need Black installed before testing.
- In your Claude Code session, ask Claude to install Black by typing a prompt like:
Install Black with pip
- Wait for Claude to run pip install black and confirm it is installed.
- Now test the hook by asking Claude to write a deliberately poorly-formatted function. Type a prompt like:
Write a new function in cli.py called multiply that takes two ints and returns their product. Deliberately use bad formatting: no spaces around operators, long lines, inconsistent indentation.
- Watch the output carefully. After Claude writes the file, you should see Black auto-format it immediately. The hook fires after the write completes and cleans up the formatting without any additional prompting.
What should I see?
After Claude writes the poorly-formatted function, you should see output indicating Black reformatted the file. The function in cli.py will have proper spacing around operators, consistent indentation, and lines within the 88-character limit.
Black not running automatically?
Confirm that black is installed by asking Claude to run black --version. If it is not found, install it with pip install black.
Check that .claude/settings.json is saved in your project's .claude directory (the same folder that contains your skills directory). If the hook still does not trigger, try restarting your Claude Code session so the configuration reloads.
Help me debug why my auto-formatting hook is not firing
Verify with /hooks
Claude Code has a built-in hooks browser that shows all registered hooks grouped by event.
- Type /hooks in your Claude Code session.
- Look for PostToolUse in the event list. It should show a count indicating one hook is configured.
- Select PostToolUse to view the hook details.
- Confirm that the matcher shows Edit|Write and the command references both python and black.
What is /hooks?
The /hooks command opens a read-only browser showing all configured hooks. You will see a list of all available hook events, with a count next to each event that has hooks configured. It is useful for confirming your configuration loaded correctly.
✔️ Awesome, I've got everything!
Great. Double check you have saved .claude/settings.json and confirmed the hook appears in /hooks.
ⓧ I'd like to double check the full code
Here is the complete .claude/settings.json file:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"command": "echo $CLAUDE_TOOL_OUTPUT | python -c \"import sys, json; data=json.load(sys.stdin); path=data.get('file_path',''); print(path)\" | xargs -I{} black {}"
}
]
}
}
Your hook is live. Every time Claude edits a Python file from now on, Black formats it automatically. Next up, you will use subagents to delegate tasks while keeping your main conversation context clean.
Use Subagents for Isolated Research
Your Claude Code session now has persistent memory, a reusable skill, and an auto-formatting hook. Every conversation you have with Claude, though, eats into a limited context window.
Subagents solve this by spinning up a separate Claude instance that does work in isolation. Only the final summary comes back to your main conversation, keeping your context clean for the work that matters most.
In this step, get ready to:
- Delegate a research task to a built-in Explore subagent.
- Delegate implementation work that edits your code.
- Understand when subagents save you context vs. when to work directly.
Delegate a research task
Claude Code has built-in subagents that handle common tasks. The Explore subagent uses read-only tools and a lightweight model to gather information without touching your files.
- In your Claude Code session, type the following prompt:
use a subagent to explore this project's structure and document all functions with their signatures
What happens when you send this?
Claude spawns an Explore subagent that runs on the Haiku model with read-only tools. It scans your project files, identifies functions, and compiles a summary.
Only the final summary returns to your main conversation. All the file-reading and analysis the subagent did stays in its own context window, not yours.
- Watch the terminal output. You should see an indication that a subagent (Explore) has been spawned.
- Once it finishes, you should see a summary listing your functions (greet and add) along with their type signatures.
Don't see a subagent spawning?
Claude sometimes handles simple requests directly instead of delegating. If it analyzed your project without spawning a subagent, try rephrasing: "Spawn a subagent to explore and document the project." The explicit instruction usually triggers delegation.
Help me get Claude Code to use a subagent for my research task.
Delegate implementation work
Subagents can also make edits. This is useful when you want to delegate a well-defined task without cluttering your main conversation with all the intermediate steps.
- Type the following prompt in your Claude Code session:
use a subagent to add comprehensive docstrings to all functions in cli.py
What does this subagent do differently?
Unlike the Explore subagent (which is read-only), this task requires file edits. Claude spawns a general-purpose subagent that inherits the main model and has access to all tools, including file writing.
The subagent reads your functions, writes detailed docstrings with Args and Returns sections, and returns a summary. Your main context only sees that summary.
- Once the subagent finishes, verify the docstrings were added by opening cli.py in your editor or by asking Claude to show the file contents.
- You should see expanded docstrings with Args: and Returns: sections on both the greet and add functions.
What should the docstrings look like?
Your greet function should now have a docstring describing the name parameter and the return value. The add function should document both integer parameters and what it returns.
Docstrings not showing up in the file?
If the subagent reported success but you don't see changes, the file might not have saved properly. Ask Claude directly: "Show me the contents of cli.py" to confirm. If docstrings are still missing, ask Claude to add them directly in your main conversation.
Help me verify that the subagent actually edited my file.
✔️ Awesome, I've got everything!
Great. Double check that your cli.py now has comprehensive docstrings on both functions.
ⓧ I'd like to double check the full code
Here is what cli.py should look like after the subagent adds docstrings:
# cli.py
def greet(name: str) -> str:
"""Return a greeting string for the given name.
Args:
name: The name to greet.
Returns:
A formatted greeting string.
"""
return f"Hello, {name}!"
def add(a: int, b: int) -> int:
"""Return the sum of two integers.
Args:
a: The first integer.
b: The second integer.
Returns:
The sum of a and b.
"""
return a + b
if __name__ == "__main__":
print(greet("World"))
Understand when to use subagents vs. main conversation
Every message in your Claude Code session adds to a limited context window. Once that window fills up, Claude loses sight of earlier messages. Subagents are your tool for keeping that window focused.
- Look at the bottom of your Claude Code terminal. You should see a context usage indicator showing how much of your context window is filled.
- Notice that the two subagent tasks you just ran only added their short summaries to your main context. All the file reading, analysis, and editing happened in separate context windows.
When should I use a subagent?
- Research or exploration that reads many files (use the Explore subagent).
- Well-defined tasks that don't need back-and-forth conversation (use a general-purpose subagent).
- Planning or architecture work where you want a summary, not a full trace of reasoning.
Keep work in your main conversation when you need iterative feedback, want to steer the direction mid-task, or the task is small enough that delegation adds overhead without saving context.
The Plan subagent
Claude Code also has a built-in Plan subagent that inherits your main model and uses read-only tools. It is ideal for asking Claude to plan a feature or refactor before you commit to implementing it.
You now have a mental model for when to delegate. In the next step, you will learn to name and resume sessions so you can spread multi-step work across multiple sittings without losing your place.
Master Session Management
You've seen how subagents keep your main conversation focused by delegating work to isolated workers. But what happens when your main session itself spans multiple sittings?
Claude Code tracks every conversation as a named session you can exit, resume, and even run in the background. In this step, you'll practice the full session lifecycle so multi-day projects feel seamless.
In this step, get ready to:
- Name and resume a session with full conversation history preserved.
- Continue a multi-step task across exits using a single flag.
- Run a background session for parallel work while you stay productive.
Name your session and exit
Every Claude Code session has an internal ID, but those are hard to remember. Naming a session gives you a human-readable handle you can use to jump back in later.
- In your active Claude Code session, rename it by typing this command:
/rename power-features-project
What does this command do?
`/rename` assigns a display name to your current session. This name appears when you list sessions later, making it easy to find and jump back into specific projects.
You should see a confirmation that the session was renamed.
- Exit Claude Code by pressing Ctrl+C or typing /exit.
- Resume your named session by running this command in your terminal:
claude --resume power-features-project
What does this command do?
`--resume` followed by a session name reopens that exact conversation. Your full message history, context, and any pending work are all restored.
You should see your previous conversation history loaded. Scroll up to confirm the messages from earlier in this project are all there.
Session not found?
Make sure you typed the session name exactly as you set it. Names are case-sensitive. Run claude --resume without a name to open an interactive picker that lists all available sessions.
Help me find my named session in Claude Code.
Continue a multi-step task across sessions
Named resume is great when you know exactly which session to reopen. But what about the common case where you just want to pick up where you left off in the current project directory?
- In your resumed Claude Code session, ask Claude to plan a new feature for your CLI tool. For example, type a prompt like:
Plan adding input validation and error handling to the greet and add functions in cli.py. Show me the plan but don't implement yet.
Why plan first?
Splitting work into plan and implement phases creates a natural break point. This lets you demonstrate that Claude remembers the plan after you exit and return.
- After Claude presents its plan, exit the session by pressing Ctrl+C or typing /exit.
- Resume the most recent session in this directory by running:
claude --continue
What does --continue do?
`--continue` (or its shorthand -c) resumes the last session that was active in your current working directory. You don't need to remember a session name.
- Ask Claude to implement the plan it described earlier. For example:
Go ahead and implement the error handling plan you described earlier.
Claude picks up exactly where it left off. It remembers the plan and implements it without you needing to repeat any context.
- Open cli.py to confirm that error handling was added to your functions.
Claude doesn't remember the plan?
If Claude asks what plan you're referring to, you may have started a new session instead of continuing. Exit and try claude --continue again. Make sure you're in the same directory where the original session ran.
Help me resume my previous Claude Code session with full context.
Run a background session
Sometimes you want Claude working on a task while you continue doing something else. Background sessions let you fire off a job and check the result later.
- Exit your current Claude Code session if one is active.
- Start a background session by running this command:
claude --bg "add error handling to all functions in cli.py"
What does --bg do?
`--bg` starts Claude as a background agent that runs independently of your terminal. The command returns immediately so you can keep working. Claude processes the task in the background using a supervisor daemon.
- While the background session runs, you can start a new interactive session or do other work in your terminal. The background task runs independently.
- Check on the background session's progress by running:
claude agents
What does this show?
`claude agents` opens a dashboard showing all running and completed background sessions. You can see their status, peek at recent output, or fully resume a finished session to review the result.
- Once the background session shows as completed, open cli.py to verify that error handling was added to all functions.
Your greet and add functions should now include type-checking logic that raises a TypeError when invalid arguments are passed.
✔️ Awesome, I've got everything!
Great. Double check you've saved your file and the error handling is in place.
ⓧ I'd like to double check the full code
Here's what cli.py should look like after the background session finishes:
# cli.py
def greet(name: str) -> str:
"""Return a greeting string for the given name.
Args:
name: The name to greet.
Returns:
A formatted greeting string.
"""
if not isinstance(name, str):
raise TypeError(f"Expected str, got {type(name).__name__}")
return f"Hello, {name}!"
def add(a: int, b: int) -> int:
"""Return the sum of two integers.
Args:
a: The first integer.
b: The second integer.
Returns:
The sum of a and b.
"""
if not isinstance(a, int) or not isinstance(b, int):
raise TypeError("Both arguments must be integers")
return a + b
if __name__ == "__main__":
print(greet("World"))
Background session didn't modify the file?
Background sessions need permission to edit files. If Claude Code is configured to ask before editing, the background session may be waiting for approval. Check claude agents to see if the session status shows it waiting for input.
Help me get my background Claude Code session to complete its task.
Secret mission
Create a Custom Security Reviewer Subagent
You've used Claude Code's built-in Explore subagent to delegate work. Now take it further by creating your own custom subagent definition file that reviews code for security vulnerabilities. Your security reviewer will use read-only tools and a focused checklist to catch common Python pitfalls.
Clean Up Your Resources
Clean Up Your Resources
This project runs entirely locally, so there are no ongoing cloud costs beyond your existing Claude subscription. Decide whether to keep your configurations (they improve every future Claude Code session), or remove them entirely.
Resources you used:
- Project folder on your Desktop (contains cli.py, CLAUDE.md, and the .claude/ directory with hooks and skills).
- User-level subagent file at ~/.claude/agents/security-reviewer.md.
- Auto memory files at ~/.claude/projects/ for this project.
- black Python package (installed via pip).
Keep everything running
No action needed. Choose this if you plan to keep using Claude Code on future projects.
- Your CLAUDE.md, custom skills, and hooks persist inside the project folder. They activate automatically whenever you run claude from that directory.
- The security-reviewer subagent at ~/.claude/agents/security-reviewer.md is available in every project on your machine.
- black remains installed and available for other Python projects.
Pause - I'll come back to this later
There are no running processes to stop. All configurations are stored as static files, so they use no memory or CPU while idle.
- If you have a Claude Code session open, exit it by pressing Ctrl+C or typing /exit.
- Everything stays in place for when you return. Resume your session later with:
claude --resume
Your named sessions, CLAUDE.md, skills, hooks, and subagent definitions will all be waiting.
Delete - I don't want to use this again
Remove all project resources and start fresh. Follow each step below.
- Delete the project folder on your Desktop. On macOS or Git Bash (Windows), run:
cd ~/Desktop
rm -rf [[PROJECT_FOLDER="your-project-folder-name"]]
On Windows PowerShell, run:
cd ~\Desktop
Remove-Item -Recurse -Force [[PROJECT_FOLDER="your-project-folder-name"]]
- Delete the user-level subagent file:
rm ~/.claude/agents/security-reviewer.md
On Windows PowerShell:
Remove-Item ~\.claude\agents\security-reviewer.md
- Delete the auto memory files Claude Code created for this project:
rm -rf ~/.claude/projects/
What does this remove?
The ~/.claude/projects/ directory stores auto memory for all your Claude Code projects. If you have other projects you want to keep memory for, navigate into the folder and delete only the subdirectory matching this project instead.
- Uninstall the black formatter:
pip uninstall black -y
Nice Work!
Nice Work!
You just transformed Claude Code from a helpful assistant into a fully configured development partner. Every project you start from here benefits from the memory, skills, and automation you set up today.
You've learned how to:
- Configure CLAUDE.md to give Claude persistent project memory and coding standards that load automatically every session.
- Create a custom /test-and-commit skill and a PostToolUse hook that auto-formats Python code after every edit.
- Delegate work to subagents for isolated research, and manage named sessions to resume multi-step work across sittings.
- (Secret Mission) Built a custom security-reviewer subagent with read-only tools and a focused system prompt for code review.
Ready to quiz yourself?