Lesson 20: 2.1.x Advanced Features
Learning Objectives
After completing this lesson, you will be able to:
- Use wildcard permission patterns
- Configure enhanced hooks for skills, agents, and commands
- Fork and rewind sessions
- Use external editor (Ctrl+G)
- Use enhanced vim motions
- Set up task dependencies
- Configure WezTerm support (2.1.33)
Prerequisites
- Completed Lessons 1-19 - Core operations and advanced features
- Permissions knowledge - Lesson 4 recommended
- Hooks experience - Lesson 8 recommended
- Vim familiarity - For vim motions section
Estimated Time: 40 minutes
Wildcard Permission Patterns
What Are Wildcard Permissions?
Wildcards allow you to create flexible permission rules that match multiple commands.
Wildcard Syntax
Basic wildcard:
{
"permissions": {
"allowedOperations": [
"Bash(*)", // Match all Bash commands
"Bash(npm *)", // Match all npm commands
"Bash(git *)", // Match all git commands
"Bash(* test)", // Match commands ending with "test"
"Bash(git * main)", // Match git commands with "main" argument
"Read(*.md)", // Match all .md files
"Edit(src/*)" // Match all files in src/
]
}
}
Wildcard Patterns
Pattern types:
-
Match all:
Bash(*)- All bash commandsRead(*)- All filesEdit(*)- All files
-
Prefix match:
Bash(npm *)- All npm commandsBash(git *)- All git commandsBash(python *)- All Python commands
-
Suffix match:
Bash(* test)- Commands ending with "test"Bash(* install)- Commands ending with "install"Read(*.md)- Files ending with .md
-
Middle match:
Bash(git * main)- Git commands with "main"Bash(npm run *)- All npm run scriptsEdit(src/**/*.ts)- TypeScript files in src/
-
Multiple wildcards:
Bash(* * *)- Commands with 3+ partsBash(git * origin *)- Git commands with origin
Wildcard Examples
Example 1: Development workflow
{
"permissions": {
"allowedOperations": [
// Git operations
"Bash(git *)",
"Bash(gh *)", // GitHub CLI
// Package management
"Bash(npm *)",
"Bash(npx *)",
"Bash(yarn *)",
"Bash(pnpm *)",
// Testing
"Bash(* test)",
"Bash(npm test)",
"Bash(pytest *)",
"Bash(jest *)",
// Building
"Bash(npm run build *)",
"Bash(* build)",
// File operations
"Read(src/*)",
"Edit(src/*)",
"Write(src/*)"
]
}
}
Example 2: Project-specific permissions
{
"permissions": {
"allowedOperations": [
// Allow all operations in tests directory
"Read(tests/*)",
"Edit(tests/*)",
"Write(tests/*)",
"Bash(* tests/*)",
// Read-only in src
"Read(src/*)",
// Specific write operations
"Edit(src/components/*.tsx)",
"Edit(src/api/*.ts)",
// Documentation - full access
"Read(*.md)",
"Edit(*.md)",
"Write(*.md)"
]
}
}
Example 3: Safe operations (don't-ask mode)
{
"permissions": {
"allowedOperations": [
// Read operations - always safe
"Read(*)",
"Bash(cat *)",
"Bash(ls *)",
"Bash(git log *)",
"Bash(git status)",
"Bash(git diff *)",
// Test commands - safe
"Bash(npm test)",
"Bash(npm run test *)",
"Bash(* test)",
// Linting - safe
"Bash(npm run lint)",
"Bash(prettier --check *)",
"Bash(eslint *)"
]
}
}
Wildcard Best Practices
-
Start specific, then generalize:
{
"allowedOperations": [
"Bash(npm test)", // Specific first
"Bash(npm run test *)", // Then pattern
"Bash(* test)" // Most general last
]
} -
Use negative patterns with deniedOperations:
{
"permissions": {
"allowedOperations": ["Bash(git *)"],
"deniedOperations": [
"Bash(git push *)", // Ban push
"Bash(git force *)", // Ban force
"Bash(git clean -fd)" // Ban clean
]
}
} -
Combine with patterns:
{
"permissions": {
"allowedPatterns": [
{
"pattern": "^Read\\(.*\\.md\\)$",
"operation": "Read"
},
{
"pattern": "^Bash\\(npm (test|lint)\\)$",
"operation": "Bash"
}
]
}
}
Enhanced Hooks System
Hooks for Skills, Agents, and Commands
In 2.1.x, hooks can be defined in:
- Skill frontmatter
- Agent definitions
- Slash command frontmatter
- Settings files
Hook Types
Available hook events:
-
Session hooks:
session-start- When starting a sessionsession-end- When ending a session
-
Tool hooks:
pre-tool- Before any tool usepost-tool- After tool completion
-
Permission hooks:
permission-request- When permission is needed
-
Agent hooks:
subagent-start- When sub-agent startssubagent-stop- When sub-agent stops
-
Command/Skill hooks:
- Hooks scoped to specific commands/skills
Skill Hooks
Pre/post tool hooks in skills:
---
name: deploy
hooks:
pre-tool:
command: ./scripts/pre-deploy.sh
once: false
post-tool:
command: ./scripts/post-deploy.sh
timeout: 300000
---
# Deploy
Deployment with automatic pre/post hooks.
Permission hooks in skills:
---
name: auto-approve
hooks:
permission-request:
command: ./scripts/approve-dev-commands.sh
---
# Auto-Approve Dev Commands
Automatically approve safe development commands.
Agent Hooks
Hooks in agent definitions:
// .claude/agents/backend.json
{
"name": "backend",
"agentType": "general-purpose",
"systemPrompt": "You are a backend developer.",
"hooks": {
"subagent-start": {
"command": "./scripts/backend-start.sh"
},
"subagent-stop": {
"command": "./scripts/backend-stop.sh"
}
}
}
Slash Command Hooks
Hooks in command frontmatter:
---
name: /deploy
hooks:
pre-tool:
command: ./scripts/check-env.sh
post-tool:
command: ./scripts/notify-deployment.sh
---
# Deploy Command
Deploy the application with environment checks.
Advanced Hook Features
Hook with additional context (2.1.x):
{
"hooks": {
"pre-tool": {
"command": "./scripts/log-tool.sh",
"additionalContext": {
"environment": "production",
"team": "backend"
}
}
}
}
Hook with once: true (run once per session):
---
hooks:
session-start:
command: ./scripts/init-dev-env.sh
once: true
---
Timeout configuration (2.1.x - increased to 10 minutes):
{
"hooks": {
"pre-tool": {
"command": "./scripts/long-running-check.sh",
"timeout": 600000 // 10 minutes (in milliseconds)
}
}
}
Hook Examples
Example 1: Pre-commit hooks
{
"hooks": {
"pre-commit": [
{
"command": "npm",
"args": ["run", "lint"]
},
{
"command": "npm",
"args": ["run", "test"]
},
{
"command": "./scripts/check-coverage.sh"
}
]
}
}
Example 2: Notification hooks
{
"hooks": {
"post-tool": {
"command": "./scripts/notify-slack.sh",
"enabledForTools": ["Bash", "Edit"],
"onlyOnFailure": true
}
}
}
Example 3: Session hooks
{
"hooks": {
"session-start": {
"command": "./scripts/session-start.sh",
"additionalContext": {
"logFile": "/tmp/claude-session.log"
}
},
"session-end": {
"command": "./scripts/session-summary.sh"
}
}
}
Session Forking and Rewind
What is Session Forking?
Forking creates a copy of your session that you can experiment with without affecting the original.
Forking a Session
Method 1: Command line
# Fork current session
claude --fork-session
# Fork and resume specific session
claude --resume session-id --fork-session --session-id new-session-id
Method 2: During session
You> /fork
Claude: I'll create a fork of this session.
[Creating fork...]
Fork created: session-abc123
Original session: session-xyz789
You're now in the forked session. Changes here won't affect the original.
Method 3: From resume screen
claude --resume
[Resume screen shows]
Session List:
session-xyz789 - Original session
[P] Preview [R] Rename
session-abc123 - Forked from session-xyz789
[P] Preview [R] Rename
Rewinding a Session
What is rewind? Undo changes by reverting to a previous point in the conversation.
Method 1: /rewind command
You> /rewind
Claude: How far do you want to rewind?
1. Last message
2. 5 messages ago
3. 10 messages ago
4. Before the last edit
5. Custom point
Choose [1-5]: 4
[Rewinding to before last edit...]
Edits undone:
- src/app.ts (reverted)
- src/utils.ts (reverted)
Session rewound successfully.
Method 2: From VS Code
[In VS Code extension]
Click "Rewind" button → Choose point → Confirm rewinding
Forking Workflows
Workflow 1: Experiment safely
1. Working on feature
2. Want to try something risky
3. Fork session
4. Experiment in fork
5. If works: Apply to original
6. If fails: Fork is discarded, original safe
Workflow 2: Parallel exploration
1. Fork session A → Session B
2. Fork session A → Session C
3. Try approach A in original
4. Try approach B in session B
5. Try approach C in session C
6. Compare results
7. Use best approach
Workflow 3: Debug vs. fix
1. Fork session
2. Original: Continue development
3. Fork: Investigate bug
4. Fork finds root cause
5. Apply fix to original
External Editor (Ctrl+G)
What is External Editor?
Press Ctrl+G to edit your current prompt in your configured text editor (vim, nano, VS Code, etc.).
Setting Up External Editor
Method 1: Environment variable
# Set default editor
export EDITOR=vim
export VISUAL=vim
# Or use other editors
export EDITOR=nano
export EDITOR="code --wait"
export EDITOR=subl
Method 2: Git config
git config --global core.editor vim
git config --global core.editor "code --wait"
Using Ctrl+G
Basic usage:
You> I need to refactor the authentication system to use OAuth2 instead
of basic auth, and I'm not sure if I should...
[Press Ctrl+G]
[Vim opens with your prompt]
# Edit in vim
I need to refactor the authentication system to use OAuth2.
The current implementation uses basic auth with sessions.
Requirements:
- Use OAuth2 with Google provider
- Store tokens securely
- Handle token refresh
- Maintain backward compatibility
[Save and quit vim]
Prompt updated with your edits!
Advanced usage - multi-line prompts:
You> [Press Ctrl+G]
[Vim opens]
Create a REST API for user management with the following endpoints:
- POST /api/users - Create user
- GET /api/users/:id - Get user by ID
- GET /api/users - List users (with pagination)
- PUT /api/users/:id - Update user
- DELETE /api/users/:id - Delete user
Requirements:
- Use Express.js
- Validate input with Joi
- Store in PostgreSQL
- Add unit tests
- Include error handling
- Add authentication middleware
[Save and quit]
Claude: I'll create a REST API for user management with those endpoints.
[Creates comprehensive API implementation]
External Editor in Skills
External editor in "Other" field (2.1.x):
Claude asks: "Which authentication method?"
Options: [1] OAuth, [2] JWT, [3] Other
You: Choose [3] Other
[Press Ctrl+G in Other input field]
[Editor opens]
Custom requirement:
Use Auth0 with social logins (Google, GitHub, Twitter)
and support enterprise SAML.
[Save and quit]
Your custom requirement is submitted!
Enhanced Vim Motions
New Vim Motions (2.1.x)
Claude Code's text input now supports enhanced vim motions for efficient editing.
New Motions
Repeat f/F/t/T:
; # Repeat last f/F/t/T motion forward
, # Repeat last f/F/t/T motion backward
Yank and paste:
y # Yank operator (copy)
yy # Yank entire line
Y # Same as yy
p # Paste after cursor
P # Paste before cursor
Text objects:
# Inner text objects (without surrounding characters)
ci" # Change inside quotes
ci' # Change inside single quotes
ci( # Change inside parentheses
ci) # Same as ci(
ci[ # Change inside brackets
ci] # Same as ci[
ci{ # Change inside braces
ci} # Same as ci{
ciw # Change inside word
ciW # Change inside WORD
# Around text objects (with surrounding characters)
ca" # Change around quotes (includes quotes)
ca' # Change around single quotes
ca( # Change around parentheses (includes parens)
ca) # Same as ca(
ca[ # Change around brackets
ca] # Same as ca[
ca{ # Change around braces
ca} # Same as ca{
caw # Change around word
caW # Change around WORD
# Also works with delete (d), yank (y), visual (v)
di" # Delete inside quotes
da" # Delete around quotes (includes quotes)
yi( # Yank inside parentheses
ya( # Yank around parentheses
Indentation:
>> # Indent line or selection
<< # Dedent line or selection
Join lines:
J # Join next line to current
Complete Vim Motion Reference
Basic movement:
h # Left
j # Down
k # Up
l # Right
w # Word forward
b # Word backward
e # End of word
0 # Start of line
$ # End of line
gg # Start of file
G # End of file
Operators:
d # Delete
c # Change
y # Yank (copy)
p # Paste
v # Visual
Motions:
f<character> # Find character forward
F<character> # Find character backward
t<character> # Till character forward
T<character> # Till character backward
; # Repeat last f/F/t/T forward
, # Repeat last f/F/t/T backward
Examples:
df) # Delete until closing paren
cf" # Change inside quotes
y$ # Yank to end of line
dgg # Delete to start of file
ci{ # Change inside braces
daw # Delete around word
Task Dependencies
What Are Task Dependencies?
Tasks can depend on other tasks, creating dependency graphs for complex workflows.
Setting Up Dependencies
Creating dependent tasks:
You> I need to implement user authentication
Claude: I'll create tasks for this work.
[Task 1] Create user model
[ ] Define User schema
[ ] Add database migration
[ ] Create User model class
[Task 2] Create authentication service
- Blocked by: Task 1
[ ] Implement login
[ ] Implement register
[ ] Implement password hashing
[Task 3] Create API endpoints
- Blocked by: Task 2
[ ] POST /api/auth/login
[ ] POST /api/auth/register
[ ] GET /api/auth/me
Tasks will execute in dependency order.
Managing dependencies:
You> Show task dependencies
Claude: Task dependency graph:
Task 1: Create user model
└─ No dependencies
Task 2: Create authentication service
└─ Depends on: Task 1
Task 3: Create API endpoints
└─ Depends on: Task 2
Flow: Task 1 → Task 2 → Task 3
Updating dependencies:
You: Add Task 4 for testing, depends on Task 3
Claude: Added task:
[Task 4] Write tests
- Blocked by: Task 3
[ ] Test login endpoint
[ ] Test register endpoint
[ ] Test authentication middleware
Updated graph:
Task 1 → Task 2 → Task 3 → Task 4
Dependency Workflows
Workflow 1: Sequential dependencies
Database → Models → API → Tests → Docs
Workflow 2: Parallel after setup
Setup → Frontend → Tests
└→ Backend ─┘
Workflow 3: Multiple dependencies
Database Models
│
┌──────┴──────┐
│ │
Auth API User API
│ │
└──────┬──────┘
│
Integration Tests
WezTerm Support (2.1.33)
WezTerm for Agent Teams
Setting teammateMode to WezTerm:
{
"teammateMode": "wezterm"
}
WezTerm configuration:
-- ~/.wezterm.lua
local wezterm = require('wezterm')
local config = {}
config.keys = {
-- Split horizontally
{
key = '|',
mods = 'CTRL|SHIFT',
action = wezterm.action.SplitHorizontal {
domain = 'CurrentPaneDomain',
},
},
-- Split vertically
{
key = '-',
mods = 'CTRL|SHIFT',
action = wezterm.action.SplitVertical {
domain = 'CurrentPaneDomain',
},
},
-- Navigate panes
{
key = 'LeftArrow',
mods = 'CTRL',
action = wezterm.action.ActivatePaneDirection('Left'),
},
{
key = 'RightArrow',
mods = 'CTRL',
action = wezterm.action.ActivatePaneDirection('Right'),
},
}
return config
✅ Check Your Understanding
-
What does
Bash(npm *)match?- Only
npm - All npm commands
- Commands ending with "npm"
- Nothing
- Only
-
How do you edit your prompt in an external editor?
- Ctrl+E
- Ctrl+G
- Ctrl+V
- Ctrl+X
-
True or False: Skills can have their own hooks.
- True
- False
-
What does
ci"do in vim mode?- Change inside quotes
- Delete inside quotes
- Yank inside quotes
- Copy quotes
-
What command forks a session?
- /clone
- /fork
- /copy
- /new
Answers: 1-b, 2-b, 3-True, 4-a, 5-b
Summary
In this lesson, you learned:
- Wildcard permissions - Flexible permission patterns
- Enhanced hooks - For skills, agents, and commands
- Session forking - Safe experimentation
- External editor - Ctrl+G for prompt editing
- Enhanced vim motions - Powerful text editing
- Task dependencies - Complex workflow management
- WezTerm support - Agent teams in WezTerm
Congratulations!
You've completed all 20 lessons of the Claude Code tutorial! You're now equipped with:
- Core operations and permissions
- Advanced features and workflows
- Multi-agent automation
- Agent teams collaboration
- Cutting-edge 2.1.33 features
Next Steps
- Practice - Use features in real projects
- Explore - Check out the ecosystem and marketplace
- Contribute - Share your skills and MCP servers
- Stay updated - Watch for new Claude Code releases
Further Reading
Happy coding with Claude Code! 🚀