
This post is about using the actual claude CLI tool itself, not about using the
best prompt techniques or plugins or whatever. I'll maybe do a plugins post later.
Useful to know what these are
| Term | What it means |
|---|---|
| Turn | One back-and-forth with the model. Claude generates a response (possibly with tool calls), reads the results, then generates again. Each of those generation steps counts as a turn. |
| Context (or context window) | The running transcript the model can see on a given turn: your messages, its messages, tool calls, tool results, system prompt, CLAUDE.md, loaded skills. Measured in tokens. |
| Compaction | When the context window fills up, Claude Code summarizes older history in-place to free space. Triggered automatically or via /compact. |
| Headless / print mode | Running claude -p "prompt" so it answers and exits instead of opening the TUI. The entry point for scripts and CI. |
| Frontmatter | The YAML block between --- markers at the top of a markdown file. Carries config like name, description, tools. |
| Hook | A shell command Claude Code runs at a lifecycle event (tool use, session start, etc.) to allow, block, or modify the action. Deterministic, not LLM-based. |
| Subagent | A child agent spawned from the main conversation. Runs in its own context window with its own tools and system prompt. Returns a summary. |
| Plan mode | Read-only exploration mode. Claude can search and read but cannot edit or run shell commands. |
Install it in a Dockerfile. I like to launch it from k8s in a CronJob from there.
vi Dockerfile
FROM node:22-slim
RUN npm i -g @anthropic-ai/claude-code
Collect the value for CLAUDE_CODE_OAUTH_TOKEN.
claude setup-token
Run the container in k8s with CLAUDE_CODE_OAUTH_TOKEN env var set. Execute the
claude command in prompt mode.
claude \
--output-format json \
--m opus \
-p $CLAUDE_PROMPT
You'll probably also want to use --permission-mode auto or --dangerously-skip-permissions
too so it doesn't freeze on permission requests. Consider some of these launch flags:
| Flag | What it does |
|---|---|
-p, --print |
Non-interactive mode: print the response and exit. The SDK / CI entry point. |
--output-format <text|json|stream-json> |
Print-mode output format. |
--input-format <text|stream-json> |
Print-mode input format. |
-m, --model <alias|id> |
Pick model for this session (sonnet, opus, haiku, or a full ID like claude-opus-4-7). |
--effort <level> |
low, medium, high, xhigh, max. Works on Opus 4.7, Opus 4.6, Sonnet 4.6. |
--mcp-config <path|json> |
Load MCP servers from file(s) or a JSON string. Repeatable. |
--strict-mcp-config |
Only use servers from --mcp-config, ignore project/user configs. |
--json-schema '<schema>' |
Constrain print-mode output to match a JSON Schema. |
--max-turns <n> |
Cap agentic turns in print mode. Exits with error when hit. |
--max-budget-usd <amount> |
Cap API spend in print mode. |
--no-session-persistence |
Don't write session to disk. Print mode only. |
--system-prompt "text" |
Replace the default system prompt. |
--append-system-prompt "text" |
Append to the default system prompt. |
--system-prompt-file <path> |
Same, from a file. Paired --append-system-prompt-file exists. |
--verbose |
Full turn-by-turn output. |
--debug [categories] |
Debug mode, optional filter like "api,hooks" or "!statsig". |
Note: --system-prompt and --system-prompt-file are mutually exclusive;
--append-* variants compose with either.
Then run it. Another example:
claude \
-p "$CLAUDE_PROMPT" \
--model sonnet \
--output-format json \
--permission-mode bypassPermissions \
--max-turns 10 \
--max-budget-usd 2.00 \
--no-session-persistence
This'd give you JSON output for parsing (datadog etc), a hard cap on agentic
turns, a dollar ceiling so a runaway job can't drain your account, and
no session file written to disk. Drop the --max-* flags if you trust
the prompt, swap bypassPermissions for auto if you want the
auto-mode classifier to gate risky calls.
Skills are procedures, agents are workers.
A skill is a directory containing a SKILL.md prompt, plus any scripts,
templates, or reference docs it ships alongside. When the skill triggers,
only SKILL.md gets injected into your current conversation as an extra
message. Claude sees it alongside everything else already in the chat,
and the skill's instructions apply for the rest of the session. The
supporting files sit in the skill directory and don't enter context
unless SKILL.md tells Claude to read them with the Read tool or run
them via Bash.
An agent runs in its own context window with its own system prompt, tool allowlist, model, and permissions. It works independently and returns only a summary. Only the agent's name and description sit in the parent conversation's context. The body stays out until the agent actually runs, and even then it only shows up in the agent's own window.
Rule of thumb:
| If the work... | Lean |
|---|---|
| Is a repeatable recipe (commit style, how to run a migration) | Skill |
| Produces a lot of intermediate output you won't reference again | Agent |
| Needs to read what's already in the conversation | Skill |
| Should run on a different model (Haiku for cost, Opus for brains) | Agent |
| Needs a tighter tool or permission scope than the parent | Agent |
| Bundles shell scripts, templates, or reference files | Skill |
| Iterates autonomously over many turns before returning | Agent |
Is one short instruction block that could live in CLAUDE.md |
Skill |
Default to a skill. If it keeps dumping logs or file contents into your main window, promote it to an agent. The cost of a skill that should have been an agent is a bloated parent context. The cost of an agent that should have been a skill is an extra round trip and less visibility into what actually happened.
I use the term "agent" and "subagent" pretty interchangeably with Claude, and I think
I'm doing that right. If there's one different, a subagent is called within a conversation
where an agent is called as a launch arg with --agent.
| Name | Model | Tools | Purpose |
|---|---|---|---|
Explore |
Haiku | read-only | File discovery, code search |
Plan |
inherit | read-only | Codebase research during plan mode |
general-purpose |
inherit | all | Multi-step tasks |
statusline-setup |
Sonnet | n/a | Used by /statusline |
Claude Code Guide |
Haiku | n/a | Answers feature questions |
| Command | What it does |
|---|---|
/simplify [focus] |
Review changed files and fix quality/efficiency issues. |
/batch <instruction> |
Orchestrate large-scale parallel changes across the codebase. |
/debug [description] |
Enable debug logging and troubleshoot. |
/loop [interval] [prompt] (alias /proactive) |
Run a prompt repeatedly. |
/claude-api |
Load Claude API reference for the session's language. |
/fewer-permission-prompts |
Scan transcripts and propose allowlist entries. |
Agents, in this context, are just .md files with a special spec. You can find them in two places:
.claude/agents/<name>.md~/.claude/agents/<name>.mdAn agent file is just some YAML frontmatter metadata props and a markdown body containing the prompt.
Only name and description are required.
Parent conversations load each available subagent's name and description so the orchestrator can decide when to delegate.
---
# Required
name: code-reviewer # lowercase + hyphens, unique
description: Reviews diffs for bugs, style, and security. Use after any code change.
# Tool and capability gates
tools: [Read, Grep, Bash] # omit to inherit everything
disallowedTools: [Bash(rm *)] # subtractive, applied after `tools`
mcpServers: [slack] # server name, or inline MCP config
skills: [code-review] # full skill content gets injected at startup
# Model and execution
model: sonnet # sonnet|opus|haiku|<full-id>|inherit (default: inherit)
effort: medium # low|medium|high|xhigh|max
maxTurns: 20 # agentic turn cap
background: false # true = always run as a background task
isolation: worktree # runs in a throwaway git worktree
# Permissions and lifecycle
permissionMode: acceptEdits # default|acceptEdits|auto|dontAsk|bypassPermissions|plan
hooks: # PreToolUse | PostToolUse | Stop, scoped to this agent
PreToolUse:
- matcher: Bash
command: ./scripts/log-tool-use.sh
memory: project # user|project|local persistent memory
# UX
color: blue # red|blue|green|yellow|purple|orange|pink|cyan
initialPrompt: "Start by listing changed files." # auto-submitted when run via --agent
---
You are a code reviewer. Read the diff, then...
Scope precedence, highest to lowest: managed org settings, --agents CLI
flag, .claude/agents/ (project), ~/.claude/agents/ (personal), plugin
agents.
You can call agents from within claude conversationally, or from the command-line
as entrypoints with claude --agent <name>.
Skills are the native Claude Code way to package reusable workflows. They
replaced .claude/commands/*.md (legacy commands still work but skills
take precedence on name collision).
| Location | Scope |
|---|---|
| Managed settings | All users in the org |
~/.claude/skills/<name>/SKILL.md |
Personal |
.claude/skills/<name>/SKILL.md |
Project |
Plugin skills/<name>/SKILL.md |
Where the plugin is enabled |
| Field | Notes |
|---|---|
name |
Slash command name. Defaults to the directory name. |
description |
Claude reads this to auto-invoke. Recommended. |
when_to_use |
Extra trigger context; appended to description. |
argument-hint |
Shown in autocomplete (e.g. [issue-number]). |
disable-model-invocation |
true = user-only; Claude won't auto-load it. |
user-invocable |
false = hide from the / menu. |
allowed-tools |
Tools auto-approved while the skill is active. |
model, effort |
Overrides for this skill. |
context |
fork to run in an isolated subagent. |
agent |
Which subagent when context: fork. |
hooks |
Hooks scoped to this skill. |
paths |
Globs limiting when the skill auto-activates. |
shell |
bash (default) or powershell for !command blocks. |
$ARGUMENTS: all args passed at invocation.$ARGUMENTS[N] or $N: specific argument, 0-indexed.${CLAUDE_SESSION_ID}, ${CLAUDE_SKILL_DIR}.!`command` inside skill content runs the command before the skill
is sent to Claude; the output replaces the placeholder. Multi-line uses
a fenced ```! block. Turn off globally with
disableSkillShellExecution: true in settings.
That has the security implications you'd expect.
Permission prompts can slow you down. For a while I tried to grant permissions to every litle thing, feels best-practice, but its so slow. I mostly just use permission-mode auto now.
| Flag | What it does |
|---|---|
--permission-mode <mode> |
default, acceptEdits, plan, auto, dontAsk, bypassPermissions. |
--dangerously-skip-permissions |
Equivalent to starting in bypassPermissions. Read the name. |
--allowedTools "Bash(git log *)" Read |
Tools that run without prompting. Space-separated list. |
--disallowedTools "Bash(curl *)" |
Tools removed from context entirely. Applied before allow. |
--tools "Bash,Edit,Read" |
Restrict the built-in tools Claude can see. "" disables all of them. |
--add-dir <path> |
Grant file access to an additional directory outside CWD. |
There are a lot of these, here's some good ones.
/btw is great, use it when you think claude is stuck/coderabbit for PR reviews but /review is nice too. It figures out your current PR itself.| Command | What it does |
|---|---|
/clear (aliases /reset, /new) |
Start a fresh conversation. Previous one is still resumable. |
/compact [instructions] |
Summarize to free context. Optional hint focuses the summary. |
/context |
Visualize current context usage as a colored grid. |
/model [alias] |
Change model. Left/right arrows adjust effort in the picker. |
/effort [level] |
low/medium/high/xhigh/max/auto. No arg opens a slider. |
/plan [description] |
Enter plan mode. |
/agents |
Open subagent manager. Left and right to nav. CRUD or run from here. |
/hooks |
View hook configs. |
/permissions (alias /allowed-tools) |
Manage allow/ask/deny rules. |
/memory |
Edit CLAUDE.md files, toggle auto-memory, view auto-memory entries. |
/mcp |
Manage MCP server connections and OAuth. |
/skills |
List available skills. Press t to sort by token count. |
/resume (alias /continue) |
Resume a conversation by ID/name or via picker. |
/rewind (aliases /checkpoint, /undo) |
Rewind conversation and code to a previous point. |
/branch [name] (alias /fork) |
Branch current conversation. |
/btw <question> |
Ask a side question that doesn't get added to history. |
/review [PR] |
Review a PR locally. |
/security-review |
Analyze pending branch changes for security issues. |
/cost |
Token usage stats. |
/usage |
Plan usage limits and rate-limit status. |
/doctor |
Diagnose the installation. |
Some notes from my testing of these:
/voice is novel but way worse than ChatGPT at recognizing what you said. I don't find it very usable./install-github-app is neat in that you don't need other infra. See instructions.| Command | What it does |
|---|---|
/ide |
Manage IDE integrations. |
/chrome |
Configure Claude in Chrome. |
/desktop (alias /app) |
Continue in Claude Code Desktop. |
/mobile (aliases /ios, /android) |
QR code to download the mobile app. |
/install-github-app |
Set up Claude GitHub Actions app. |
/install-slack-app |
Install Claude Slack app. |
/remote-control (alias /rc) |
Expose session to remote control. |
/teleport (alias /tp) |
Pull a web session into this terminal. |
/ultraplan <prompt> |
Draft plan in ultraplan session, execute remotely. |
/ultrareview [PR] |
Multi-agent cloud code review. |
/autofix-pr [prompt] |
Spawn web session to push fixes when CI fails. |
/schedule [description] (alias /routines) |
Create/list/run routines. |
/plugin, /reload-plugins |
Plugin management. |
/sandbox |
Toggle sandbox mode (supported platforms only). |
/voice |
Push-to-talk voice dictation. |
| Key | Effect |
|---|---|
Esc |
Cancel the current generation. |
Esc Esc |
Rewind to a previous checkpoint (conversation and code). |
Shift+Tab (or Alt+M) |
Cycle permission modes: default → acceptEdits → plan → auto → bypassPermissions. |
Ctrl+C |
Cancel current input or generation. |
Ctrl+D |
Exit the session. |
Ctrl+L |
Clear the prompt input and redraw (keeps history). |
Ctrl+R |
Reverse search command history. |
Ctrl+O |
Toggle transcript viewer. |
Ctrl+B |
Background the running bash task. In tmux, press twice. |
Ctrl+T |
Toggle task list in the status area. |
Ctrl+X Ctrl+K |
Kill all background agents. Press twice within 3s to confirm. |
Ctrl+G or Ctrl+X Ctrl+E |
Open the current prompt in $EDITOR. |
Option+P / Alt+P |
Switch model without clearing the prompt. |
Option+T / Alt+T |
Toggle extended thinking. |
Option+O / Alt+O |
Toggle fast mode. |
| Key | Effect |
|---|---|
Ctrl+A / Ctrl+E |
Start / end of line. |
Ctrl+K |
Delete to end of line. |
Ctrl+U |
Delete to start of line. |
Ctrl+W |
Delete previous word. |
Ctrl+Y |
Paste last deleted text. |
Alt+Y (after Ctrl+Y) |
Cycle paste history. Requires "Use Option as Meta Key" in iTerm |
Alt+B / Alt+F |
Back / forward a word. Requires "Use Option as Meta Key" in iTerm |
| Terminal | Newline binding |
|---|---|
| Any terminal | \ then Enter |
| macOS default | Option+Enter |
| iTerm2, WezTerm, Ghostty, Kitty | Shift+Enter (no config needed) |
| VS Code, Alacritty, Zed, Warp | Run /terminal-setup to install Shift+Enter |
| Control sequence (anywhere) | Ctrl+J |
| Prefix | What it does |
|---|---|
/ |
Slash commands and skills. |
! |
Bash mode: run a shell command and add the output to context. |
@ |
File path autocomplete. |
Hold Space |
Push-to-talk dictation (if /voice is on). |
A worktree is git concept,
it basically lets you work on more than one branch at a time. You'll see it saved to .claude/worktrees/.
Don't forget to gitignore them.
| Flag | What it does |
|---|---|
-w, --worktree <name> |
Start in a git worktree at <repo>/.claude/worktrees/<name>. |
--tmux |
Pair with --worktree to open in a tmux pane. |
I personally use this with multiple tmux sessions across a single repo so I can work on more than one thing at a time. You do end up with the usual merge conflict situation, but claude's pretty good about sorting that out on its own too.
I'm personally a tmux nerd, I'm genuinely just a happier person with tmux running, so
the --tmux flag existing is exciting to me. It's kind of janky though, it claims it
should open a pane but at the time of my writing this it opens it into a new session
and puts the original pane you ran it in into a blocking state, so personally I'd
just manage the worktrees myself for now.
Often you need to quit to reload MCP tools or reboot. You might also want to just revisit an prior conversation. Sessions are saves of where your context left off.
Show current session UUID:
ls -t ~/.claude/projects/$(pwd | sed 's|/|-|g')/*.jsonl | head -1
When you exit a claude session it'll often print the --resume command for you at
the bottom. If you missed it, you can use claude --continue to jump back in:
claude
> do the thing
> exit
claude --continue
| Flag | What it does |
|---|---|
-c, --continue |
Resume the most recently exited conversation in the current directory. Basically -r with the arg pre-filled |
-r, --resume [name|id] |
Resume a specific session by name or UUID, or open an interactive picker. |
--fork-session |
With --resume or -c, create a new session ID instead of reusing the old one. Good for branching. |
--session-id <uuid> |
Use a specific UUID for the session. |
It's like starting claude twice in the same directory, but without using worktrees. The changes all go to the same branches and locations on the filesystem. You resume from where the most recent session left off.
claude # or if you plan ahead, "claude --name foobarbaz"
> do the foo
> /rename foobarbaz # if you didn't set the name ahead of time
... # in another window
claude --fork-session --resume foobarbaz
I you just do --resume it'll let you pick from session history, and -c picks the newest.
When to use session forking:
/compact but you're afraid of losing something importantExample:
SESSION=$(uuidgen)
claude --session-id $SESSION
~/.claude/projects/<cwd>/<uuid>.jsonl).
You can tail -f it, attach a log shipper, or register a webhook against it without polling the filesystem to figure out which file is "yours."| Command | What it does |
|---|---|
/rename [name] |
Rename current session. |
/export [filename] |
Export conversation as plain text. |
/copy [N] |
Copy the Nth-to-last assistant response to clipboard (0 = last). |
/diff |
Interactive diff viewer for uncommitted and per-turn changes. |
/tasks (alias /bashes) |
Manage background tasks. |
/recap |
One-line session summary on demand. |
/stats |
Daily usage, session history, streaks. |
/insights |
Report analyzing your Claude Code sessions. |
/focus |
Toggle focus view (fullscreen renderer only). |
/color <name> |
Prompt bar color: red, blue, green, yellow, purple, orange, pink, cyan. |
Hooks are shell commands Claude Code runs at specific lifecycle events.
You define them in settings.json. They
receive JSON on stdin (including session_id, tool_name, arguments),
and their exit code or JSON output can allow, block, or modify the action.
Personally, I care about hooks mostly for security and logging/notifications.
Typical uses:
rm -rf or edits to .env (PreToolUse + exit 2).prettier or gofmt after every Edit (PostToolUse).UserPromptSubmit).Stop).The /hooks slash command shows what's registered and where each rule
came from (user, project, managed, or plugin).
I'd originally done like a whole write-up on how to make hooks, but honestly just ask Claude to make them for you. I might give Hooks their own post.
At launch, Claude Code walks the directory tree from CWD to root and concatenates
CLAUDE.md and CLAUDE.local.md from each directory. Nothing gets
overridden. It all loads. During the session, when Claude edits a file it'll also
load in nested CLAUDE.md files, like if Claude opens src/api/auth/login.ts, it'll pick
up src/CLAUDE.md, src/api/CLAUDE.md, src/api/auth/CLAUDE.md (if any exist, but only at that moment).
| Location | Scope | Shared |
|---|---|---|
macOS: /Library/Application Support/ClaudeCode/CLAUDE.md |
Managed org-wide | deployed by IT |
Linux/WSL: /etc/claude-code/CLAUDE.md |
Managed | same |
Windows: C:\Program Files\ClaudeCode\CLAUDE.md |
Managed | same |
./CLAUDE.md or ./.claude/CLAUDE.md |
Project | yes (git) |
~/.claude/CLAUDE.md |
Personal | no |
./CLAUDE.local.md |
Local | no (gitignored) |
.claude/rules/ is a directory you fill with topic-scoped markdown files instead of
combining everything into one big CLAUDE.md. They behave like CLAUDE.md
(loaded into context at session start, treated as instructions, not enforcement) but
they're organized by file.
paths load unconditionally.~/.claude/rules/.To differentiate these from the usual CLAUDE.md, you need to set which paths they apply
to. Add a paths frontmatter field to scope a file to specific globs:
---
paths:
- "src/api/**/*.ts"
---
API-specific rules
foo bar baz