Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Latest commit

 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 

Repository files navigation

🎓 Hands-On Coding Practice for Claude Code

A small Claude Code Skill + Rule that turns selected parts of implementation work into guided coding practice.

Claude prepares the tests, structure, interfaces, and supporting code — then leaves you a few carefully chosen building blocks to write yourself.

Built for TDD work where you want to keep sharpening your own implementation skills instead of letting the agent write 100% of every feature. You pick how much you want to write, from nothing to a lot. Claude writes every test, and the suite stays red until your part is correct.

Install

Two commands. The first installs the Skill, the second installs the Rule that triggers it.

# 1. the Skill (the workflow)
npx skills@latest add ctxr-dev/hands-on --skill hands-on --agent claude-code --global

# 2. the Rule (the trigger + tier question)
mkdir -p ~/.claude/rules
curl -fsSL https://raw.githubusercontent.com/ctxr-dev/hands-on/main/rules/hands-on.md \
  -o ~/.claude/rules/hands-on.md

Restart Claude Code and ask for any implementation task.

Other install options

From a local clone

npx skills@latest add . --skill hands-on --agent claude-code
cp rules/hands-on.md ~/.claude/rules/hands-on.md

Project-level instead of global — drop --global from the skills command (installs to .claude/skills/), and copy the rule to .claude/rules/hands-on.md in your project root instead of ~/.claude/rules/.

Track the repo instead of copying — symlink the rule:

ln -sf "$PWD/rules/hands-on.md" ~/.claude/rules/hands-on.md

Inspect before installing

npx skills@latest add ctxr-dev/hands-on --list

Useful flags: -g / --global for user level, --copy to copy files instead of symlinking them.

Two separate steps are needed because the Skills CLI installs Skills — it does not place arbitrary files into Claude Code's rules directory.

What it looks like

You ask for a feature. Claude asks how much you want to write yourself:

🎓 How much of this implementation would you like to write yourself?

  ▸ Tier 0 — Claude does everything
  ▸ Tier 1 — Light practice
  ▸ Tier 2 — Balanced practice
  ▸ Tier 3 — Deep practice

Real example:

Hands-On Example

You pick Tier 1. Claude implements the use case, the parser, the persistence wiring, and writes every test — then stops at the one part worth learning:

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🎓  HANDS-ON PRACTICE  ·  Tier 1  ·  1 gap
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

I left one meaningful building block for you.
The tests and surrounding code are ready.

▸ Your gap
  `src/domain/service.py:42` — decide when an order may be cancelled

▸ Run this to check your work
  pytest tests/domain/test_service.py::test_cancel_rules -q

▸ Expected behavior is defined in
  `tests/domain/test_service.py`

  Right now it fails with:
  NotImplementedError: hands-on gap

💡 Start by tracing how an order reaches this point, and what
   the caller expects back when cancelling is not allowed.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

In the code, the gap is a real TODO you can think with:

def can_cancel(self, order: Order) -> bool:
    # TODO(hands-on):
    # You are implementing this part yourself.
    #
    # Goal:
    # Decide whether this order is still allowed to be cancelled.
    #
    # Think about:
    # - Which order states make cancelling impossible, and why?
    # - Once an order has shipped, does the time window still matter?
    # - What should happen for an order that was already cancelled?
    #
    # Expected behavior is defined in: tests/domain/test_service.py
    # Run it with: pytest tests/domain/test_service.py::test_cancel_rules -q
    #
    # Start by tracing how the input reaches this point and what
    # the caller needs back.
    raise NotImplementedError("hands-on gap")

You ask for a hint. Claude goes one step deeper — never to the answer:

The window check and the state check are doing different jobs. One of them is about time, the other about what already happened to the order. Look at the third test case: it passes a shipped order inside the window. What does it expect, and what does that tell you about which check wins?

You write it and run the command. The test goes green — no other edit needed anywhere. Then Claude wraps up:

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🎓  HANDS-ON COMPLETE
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

You implemented:  can_cancel() cancellation rules
Claude implemented:  CancelOrder use case, parser, repository wiring, 14 tests
Remaining TODOs:  0
Tests:  38 passed

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Not in the mood? Say stop practice, finish it, or take over at any point and Claude completes everything itself.

The TDD contract

This is what makes it real practice rather than decoration.

You never write tests. Claude writes and owns every test. Practice gaps live only in production code — never inside a test file, never as a missing assertion for you to fill in. Writing tests is not the skill being practiced here.

The tests fail while your gap is open. Before handing off, Claude verifies three things:

  1. the tests actually fail — otherwise the gap is fake and the behavior already exists somewhere
  2. they fail for the right reason — a clean assertion failure from the missing behavior, not a syntax or import error
  3. filling the gap correctly is sufficient — when your implementation is right, the tests go green with no other edit anywhere

A red test at your gap is the assignment, not a bug. Claude will not fix it, weaken the assertion, skip the test, or adjust it to match the stub. If your attempt fails, Claude explains what the failure is telling you.

You always get the exact command to check yourself — the narrow one for a fast loop, and the broader project command for when you think you are done, both derived from the repository's real tooling.

After creating the gaps, Claude stops. An open gap is the finished state of Claude's part; it will not quietly fill it in.

Practice tiers

Tier Small change Larger change
0 0 gaps 0 gaps
1 1 gap up to 2–3 gaps
2 1–2 gaps about 2–4 gaps
3 2–3 gaps 4–5 gaps

These are targets, not a quota. Claude should prefer fewer, better gaps over artificial fragmentation.

A gap should be a meaningful building block: core logic, a domain operation, an important transformation, a state transition, or another reusable engineering concept.

It should not be a random TODO, boilerplate, import, trivial wiring, or security/data-loss critical code.

If you skip or cancel the tier question, you get Tier 0 — normal behavior, Claude implements everything.

The teaching behavior

The TODO deliberately does not contain the answer. It tells you what responsibility you are implementing, what constraints matter, what to think about, and which test defines the expected behavior. The wording is plain English, not academic.

When you ask for help, Claude teaches progressively — pointing at the code path, then the constraint, then the data flow, then the edge cases. It can explain concepts, APIs, invariants, trade-offs, and testing strategy. It must not hand you the final implementation for an active gap, in any disguise: no complete code block, no patch, no replacement function, no line-by-line instructions.

Asking for "more details" gets you more explanation, not more finished code.

Repository layout

hands-on/
├── README.md
├── rules/
│   └── hands-on.md
└── skills/
    └── hands-on/
        └── SKILL.md
  • skills/hands-on/SKILL.md — the installable Skill, containing the detailed workflow.
  • rules/hands-on.md — the small persistent rule: only the trigger and the tier decision.

Why both a Skill and a Rule?

The Rule is the small, always-loaded policy:

ask me whether I want practice; otherwise behave normally.

The Skill is the larger playbook, loaded only when relevant:

how to choose good gaps, how to keep the tests honest, how to write useful TODOs, how to teach without giving away the answer, how to stop practice, and how to present the session.

Rule files are injected into every session, so they cost context permanently. That is why the rule stays tiny and the workflow lives in the Skill. When editing either file, keep that split — do not migrate workflow detail into the rule.

Design principles

Learning should be inside real work. The practice gaps are part of the actual feature, not toy exercises.

The user chooses the difficulty. Tier 0 is always a valid choice.

Tests are the specification, not the exercise. Claude writes them so they can be trusted as the source of truth you are coding against.

The agent handles the boring parts. Setup, repetitive wiring, test plumbing, investigation, and verification should not consume your practice slots.

Hints should preserve thinking. A hint should help you get unstuck without turning the task into copying.

Stopping practice should never leave the feature unfinished. An explicit request to take over means Claude finishes the implementation.

No behavior changes just for the lesson. The original product requirements remain the source of truth.

Verify the installation

Start Claude Code in a test repository and ask for a small TDD change. You should see the tier question before Claude creates any practice gap.

Test the tier paths:

  • Tier 0 → Claude implements everything
  • Tier 1 → one meaningful gap on a small task
  • Tier 3 → several meaningful gaps
  • cancel/skip the question → Tier 0 behavior

Then test a lesson end to end:

  1. check that the TODO is in production code, never in a test
  2. run the command Claude gave you and confirm the test is red
  3. ask for more detail, then ask again — the hints should deepen without becoming the answer
  4. implement the TODO yourself and confirm the test goes green with no other edit
  5. say stop practice and verify Claude finishes any remaining gaps

The final code quality should match a normal implementation. The only difference is who wrote selected building blocks.

About

Skill which helps you to not lose your hands on skill during LLM development era

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors