Skip to content

Efficiency hacks for daily Claude Code work

Claude Code efficiency hacks are repeatable habits that cut wasted turns and tokens: one task per session with /rename and /clear, scoped file reads, lower effort for mechanical work, shell helpers built on claude -p, and JSON output for scripts. The rule that binds them: none may remove the test gate that proves the result.

This page is for developers who already use Claude Code every day. You know the symptoms: a session that started as a bug fix is now three tasks deep, every answer takes longer, Claude reads dist/ before touching the one file you named, and you retype the same “review this diff” prompt ten times a week. The fixes below take minutes to set up and pay back on every task.

What you get from these Claude Code habits

Section titled “What you get from these Claude Code habits”
  • A measured baseline, so you know whether a hack helped or only felt faster.
  • A session routine that keeps context small without losing work: name, hand off, clear, resume.
  • Permission rules and CLAUDE.md lines that stop Claude reading generated files and over-summarising.
  • Six shell helpers that do not shadow real commands and do not need approvals they cannot get.
  • A /rev-staged skill that replaces a review prompt you retype every week.
  • Scriptable output with --output-format json and --json-schema, checked by jq -e instead of by eye.
  • A verification rule that keeps targeted tests fast during iteration and the full gate before “done”.

How do you know an efficiency hack worked?

Section titled “How do you know an efficiency hack worked?”

Measure before you change anything. Two built-in commands give you the numbers (checked on Claude Code 2.1.283):

CommandWhat it showsUse it to
/contextCurrent context use as a coloured grid (/context all for detail)See how much of the window is CLAUDE.md, MCP tool definitions, file reads and conversation
/usageSession cost, plan limits and activity stats (/cost and /stats are aliases)Compare the cost of the same kind of task before and after a change

Run /context at the start of a fresh session and again after a typical task. If a large share of the window is taken before you type anything, the fix is a shorter CLAUDE.md or fewer MCP servers, not a cleverer prompt — see pruning CLAUDE.md and AGENTS.md. Team-level spend tracking belongs on the cost control page.

Order matters: each step makes the next one measurable, and the gate goes in before any hack that reduces checking.

OrderHabitSet-upWhy this position
1Baseline with /context and /usagetwo commandsWithout it you cannot tell a real saving from a feeling
2Test gate in CLAUDE.mdthree linesEvery later hack reduces work; this keeps the proof
3One task per sessiona routine, no configThe biggest context saving, and free
4Deny rules for generated filesone settings fileEnforced, so it keeps working when a prompt forgets
5Effort and output styleone commandCheap to try, and easy to undo per task
6Shell helpers, skills and JSON outputa shell profile edit, one SKILL.mdPays back only once you repeat the task weekly

Stale context from the previous task makes every later turn slower and more expensive, and it pulls irrelevant files into Claude’s reasoning. The routine below keeps each session to one task without losing anything.

  1. Name the session when you start it. Start with claude -n payment-retry, or run /rename payment-retry inside a running session. The name appears in the /resume picker and the terminal title.

  2. Ask side questions with /btw. /btw what does the retry decorator in src/lib/http.ts do? answers without interrupting the main conversation, so a quick lookup does not become part of the task’s context.

  3. Write a handoff note before you switch. Use the handoff prompt below. The note survives any later /compact or /clear, and it is the input for the next session.

  4. Run /clear. It starts a new session with empty context. The previous session stays on disk and you can reopen it from /resume.

  5. Resume by name when you come back. claude -r payment-retry opens the resume picker filtered by that search term; claude -c continues the most recent session in the current directory.

When you must stay in one long session, compact with explicit instructions instead of waiting for automatic compaction:

/compact Keep: files I edited, the failing test names and their last output, decisions and why. Drop: exploratory file reads, rejected approaches, command output already summarised.

To avoid retyping that, add a standing rule to CLAUDE.md; the summariser reads it along with the rest of the conversation. The cost control page uses the same pattern:

# Compact instructions
When compacting, preserve test output, error traces, file paths you changed and decisions with their reasons.
Summarise discussion. Drop exploratory reads that led to no change.

In the new session, start with: Read .claude/handoff.md, run the proving command first, and tell me if the result differs from the note before you continue. Add .claude/handoff.md to .git/info/exclude if you do not want it committed. If you would rather install a ready-made handoff routine than keep this prompt, see skills for context and token discipline.

Claude Code explores before it edits, which is right for unfamiliar work and wasteful for a named bug. Scope the task in the prompt, and fence off generated files in settings so the rule holds even when a prompt forgets.

Fence generated files with permission rules. A Read(...) deny rule in .claude/settings.json stops the file tools from opening those paths; the same file can be committed so the whole team gets it:

{
"permissions": {
"deny": [
"Read(./dist/**)",
"Read(./build/**)",
"Read(./coverage/**)",
"Read(./package-lock.json)"
]
}
}

A deny rule is enforced; a CLAUDE.md line such as “never read dist/” is only guidance. Use the rule for anything you never want in context, and keep CLAUDE.md for behaviour. See memory and CLAUDE.md for where each instruction belongs.

Cut the closing summary. Run /output-style and choose Concise (one of the four built-in styles), or add one line to CLAUDE.md:

After a change, do not summarise it. Show the changed file paths and the test command you ran with its result.

Match effort to the task. Claude Opus 5.5, the Claude Code default from v2.1.280 on the latest release channel, runs at medium effort (the stable channel still starts on an older default; /model shows what you have). Drop to low for mechanical edits (renames, formatting, boilerplate) with /effort low or claude --effort low, and raise it to high when Claude misses something, before you consider another model. The models hub lists the current models and when to change.

Two details decide whether a helper saves time or causes trouble. First, prefix every name: the popular alias cc='claude -c' shadows the C compiler in your shell. Second, a claude -p run starts in Manual permission mode with nobody to approve an edit, so one-shot helpers stay read-only and anything that writes files opens an interactive session.

Terminal window
# ~/.zshrc or ~/.bashrc — every name starts with "cl" so nothing shadows a real command
alias clq='claude -p' # one-shot, read-only question
alias clc='claude -c' # continue the latest session in this directory
alias clr='claude -r' # resume picker; clr payment-retry filters by name
# Review the staged diff; reports only, never edits
clrev() {
git diff --cached | claude -p "Review this staged diff. Report only bugs, security issues and missing tests, each with file:line. If there are none, reply 'No findings' and nothing else."
}
# Explain a file and its blast radius
clexplain() {
claude -p "Explain what $1 does, which modules call it, and what breaks if its exported functions change. Read only $1 and the files that import it."
}
# Write tests: interactive, because it edits files and runs them
cltest() {
claude -n "tests-$(basename "$1")" "Write tests for $1 following the nearest existing test file. Run them and show me the output."
}

Before you add them, run type clq clc clr clrev clexplain cltest and confirm each prints “not found”. Piping build and test output into Claude is covered on the terminal mastery page.

A shell helper works outside a session; inside one, the same prompt belongs in a skill. Save the file below as .claude/skills/rev-staged/SKILL.md and commit it, and every teammate gets /rev-staged with the same wording (skill format checked against Claude Code 2.1.283):

---
description: Review the staged diff for bugs, security issues and missing tests
disable-model-invocation: true
allowed-tools: Bash(git diff *)
---
Review this staged diff. Report only bugs, security issues and missing tests,
each with file:line. If there are none, reply "No findings" and nothing else.
!`git diff --cached`

Three lines decide how it behaves:

  • The !`git diff --cached` line runs before Claude sees the skill, so the diff arrives inlined and Claude spends no turn fetching it.
  • disable-model-invocation: true means only you can trigger it, and it keeps the skill out of Claude’s context until you do, so it costs no tokens in sessions that never use it.
  • allowed-tools pre-approves the injected git diff for that one invocation; without it, the injection can stop and wait for approval.

Frontmatter mistakes fail silently, which is why custom commands and skills adds a CI lint for skill files. Use a skill when the prompt runs inside a session and a shell helper when you want an answer without opening one.

When Claude’s answer feeds another command, ask for JSON and check its shape mechanically. --output-format works only with -p.

Terminal window
# Plain answer as a string: read .result
claude -p "List every HTTP route in src/api with its method and handler file, one per line." \
--output-format json | jq -r '.result'

For fields you can rely on, add --json-schema. The validated object lands in structured_output, next to the run metadata:

Terminal window
claude -p "Find source files in src/api that have no matching test file." \
--output-format json \
--max-budget-usd 1 \
--json-schema '{"type":"object","properties":{"untested":{"type":"array","items":{"type":"string"}}},"required":["untested"]}' \
> untested.json
jq -e '.structured_output.untested | type == "array"' untested.json >/dev/null \
&& jq -r '.structured_output.untested[]' untested.json

jq -e exits non-zero when the check fails, so a script stops instead of acting on a malformed answer. --max-budget-usd caps what a runaway print-mode run can spend, and the same JSON carries total_cost_usd if you want to log it. For CI jobs and larger pipelines, go to Claude Code automation.

The most tempting hack is to stop running tests. Do it only in the shape below: targeted tests while iterating, the full gate before anything is called done. Then you verify behaviour from test output rather than by reading every changed line.

# Test scope (CLAUDE.md)
- While iterating, run only the tests for files you changed: npx vitest run <path>
- Before you say a task is done, run: npm run typecheck && npm run lint && npm test
- Report each command with its exit status. Never call a task done with a failing or skipped test.

Three layers back that rule up:

  • A Stop hook can run the gate automatically when Claude finishes a turn, so the rule no longer depends on the model remembering it. See hooks automation.
  • /code-review before you commit gives a second pass focused on bugs, not style. See review automation.
  • CI runs the same commands, so a local shortcut can never be the last check.

All flags below are from claude --help on version 2.1.283.

Terminal window
# Give Claude tool access to a sibling repository in the same session
claude --add-dir ../shared-components
# Fall back to other models when the primary is overloaded or unavailable
claude --model opus --fallback-model sonnet
# Resume the session linked to pull request 123 (or pick from linked sessions)
claude --from-pr 123

--fallback-model accepts a comma-separated list and retries the primary model at the start of each user turn, so a fallback lasts one turn, not the whole session. If a fallback turn produced a weaker answer, rerun that step once the primary is back. More flags and commands are collected on features you have not tried and slash commands mastery.

When Claude Code efficiency hacks backfire

Section titled “When Claude Code efficiency hacks backfire”
SymptomCauseRecovery
cc (or another short alias) runs Claude instead of the tool you expectedThe alias shadows an existing commandunalias cc, rename helpers with a unique prefix, check with type
A helper prints nothing useful or says it could not editclaude -p starts in Manual mode and cannot get approvalKeep -p helpers read-only; run editing helpers interactively
You cleared the wrong session/clear was run before the handoff/resume and pick the old session by name; /rewind can also restore from before /clear
After /compact, Claude forgets a decision or re-reads filesThe summary dropped itRestate it once, then add it to your compact instructions or the handoff note
Claude edits without reading callers and breaks themScope rules are too tight for the taskWiden the prompt for this task (“read callers of formatInvoiceTotal”); keep deny rules for generated files only
Targeted tests pass, CI failsA change broke code outside the tested pathKeep the full gate in CLAUDE.md and a Stop hook; never let the targeted rule become the only rule
/rev-staged does not appear, or Claude runs it unaskedThe frontmatter is misspelt or the opening --- is not on line 1, so Claude Code ignores itFix the file, restart the session, and add the skill lint from custom commands and skills
A script acted on a half-formed answerOutput parsed without a schemaAdd --json-schema and a jq -e check before the next command

Where to go next with Claude Code efficiency

Section titled “Where to go next with Claude Code efficiency”