Claude Code Best Practices for RHDP

The complete guide to working effectively with Claude Code
ℹ️
Who this is for: RHDP developers who use Claude Code daily across AgnosticV, AgnosticD, and Showroom repos. Whether you're creating catalog items, writing workshop content, or building validation roles, this page covers how to configure Claude Code for maximum effectiveness.

Managing Your CLAUDE.md

CLAUDE.md is Claude’s persistent memory. Unlike a chat prompt, it loads automatically on every session — no need to re-explain your conventions. But it only works if it’s kept lean and precise.

The File Hierarchy

Three layers load on every session, additively:

~/CLAUDE.md                           # Global — applies to ALL repos, ALL sessions
~/work/code/agnosticv/CLAUDE.md       # Project — applies to this repo only
~/work/code/agnosticv/.claude/rules/  # Rules — always active, modular

Global ~/CLAUDE.md — rules that never change regardless of repo:

Project CLAUDE.md — checked into git, repo-specific:

.claude/rules/ directory — modular, auto-load every session:

.claude/rules/
  git-conventions.md     # Branch naming, commit format
  yaml-standards.md      # YAML formatting rules
  naming-conventions.md  # Variable and file naming

Rules files let you split concerns without one giant CLAUDE.md. Each file loads automatically — no configuration needed.

What to Include vs Exclude

Include:

Exclude:

⚠️
Keep it under 200 lines. A bloated CLAUDE.md causes Claude to miss rules buried deep in it. If Claude keeps ignoring a rule that's in the file, the file is too long. Prune it — remove anything Claude already knows.

RHDP Repo Examples

AgnosticV CLAUDE.md:

## AgnosticV Repository

### Structure
- Catalogs: agd_v2/<category>/<name>/ (standard)
- Enterprise: enterprise/<category>/<name>/
- Key files: common.yaml, dev.yaml, description.adoc

### Rules
- Validate YAML with yamllint before committing
- Asset UUIDs must be unique (generate with uuidgen)
- Branch from main, PR to main
- No feature/ prefix on branches
- No AI attribution in commits

### Naming
- Catalog names: lowercase with hyphens
- Branch names: short, descriptive (e.g., update-aap-catalog)

Showroom CLAUDE.md:

## Showroom Workshop

### Content Format
- AsciiDoc (.adoc), NOT Markdown
- Files: content/modules/ROOT/pages/
- Navigation: content/modules/ROOT/nav.adoc

### Writing Style
- Second person ("you will", not "we will")
- Use %user% for username substitution (never {user})

### AsciiDoc Patterns
- [source,bash,role=execute,subs=attributes+] for commands (not [source,bash] alone)
- [NOTE]/[IMPORTANT]/[WARNING] for callouts
- Every action needs a verification step

AgnosticD CLAUDE.md:

## AgnosticD v2 Repository

### Roles
- Path: roles/ocp4_workload_<name>/
- Inherit from core_workload patterns
- All oc/ansible commands: delegate_to: bastion
- Register results and check with assert

### Naming
- Roles: ocp4_workload_<descriptive_name>
- Variables: role_name_variable_name

@-Imports for Shared Context

CLAUDE.md supports `` syntax to pull in other files without duplicating them:

{{~/claude/agnosticd-context}}
{{~/claude/litemaas.md}}

Use this for large reference documents that multiple repos need — keep CLAUDE.md short and import the detail on demand.

Real Example: Work Log

A good global rule defines a trigger phrase, an exact format, and where to write output. The work log pattern does all three:

## Work Log

Maintain a running log in ~/work-log/ for quarterly reviews.
One file per quarter: 2026-Q1.md, 2026-Q2.md, etc.

When the user says "log this" or "write log":
1. Determine the current quarter from today's date
2. Open (or create) ~/work-log/YYYY-QN.md
3. Find the Monday of the current week for the section header
4. If a "## Week of YYYY-MM-DD" section exists, append bullets under it
5. If not, add a new section at the TOP of the file (most recent first)
6. Write concise, action-oriented bullets

Format:
## Week of 2026-02-10
- Built validation role for AAP2 catalog item
- Fixed Showroom module 3 AsciiDoc formatting

This belongs in ~/CLAUDE.md because it applies across every repo and every session. The trigger phrase means Claude acts on it without you having to remember — just say “log this” at the end of any session.

Staying Current


Choosing and Switching Models

Claude Code supports three model tiers. The right model depends on what you’re doing.

Available Models

ModelBest ForCost
Sonnet (default)Daily work — editing files, running commands, writing code, using skillsLower
OpusComplex architecture, multi-file refactoring, nuanced content generationHigher
HaikuQuick lookups, simple questions, fast responsesLowest

How to Switch Models

For the current session:

> /model

This opens an interactive picker. Select the model you want.

When starting Claude:

claude --model opus

Set a default model permanently:

claude /config

Navigate to the model setting and change it. This persists across sessions.

Tip: Use Sonnet for everyday RHDP work (catalog items, showroom modules, validation roles). Switch to Opus when you need Claude to understand complex relationships across multiple files -- like building a new AgnosticD role that inherits from core_workload while generating matching AgnosticV catalog configs.

Context Management

Every Claude Code session has a context window – a limit on how much information Claude can hold at once. Managing it well prevents Claude from “forgetting” your conventions mid-task.

Check Your Context Usage

> /context

This shows how much of the context window is in use. When it gets above 70-80%, Claude may start losing details from earlier in the conversation.

Clear Context Between Tasks

> /clear

Use /clear when switching between unrelated tasks. If you just finished an AgnosticV catalog item and now need to write Showroom content, clear first. Otherwise Claude carries over YAML patterns into your AsciiDoc files.

Compact Without Losing Everything

> /compact Keep the role naming conventions, delegate_to patterns,
> and the validation task structure from core_workload

/compact summarizes the conversation to free up space while preserving what you specify. Use it when you’re deep in a long session and don’t want to start over.

⚠️
Auto-compact happens automatically when context reaches ~95%. When this fires, Claude summarizes everything -- and summaries lose detail. To avoid surprises, compact proactively with focus instructions before auto-compact triggers.

What to Preserve During Compaction

When compacting during a Showroom session:

> /compact Keep the AsciiDoc patterns from module-01.adoc,
> the %user% variable format, the [NOTE]/[IMPORTANT] callout style,
> and the verification step pattern. I still need modules 4 and 5.

When compacting during an AgnosticD session:

> /compact Keep the role naming conventions, delegate_to: bastion pattern,
> core_workload inheritance, and the validation task structure

Session Management

Name Your Sessions

Always name your session when starting real work:

> /rename agd-aap-validation-role

Resume After Interruptions

Claude saves every session locally. If your laptop restarts, VPN drops, or you close the terminal:

# Resume the most recent session in this directory
claude --continue

# Pick from a list of recent sessions
claude --resume

# Resume a specific named session
claude --resume agd-aap-validation-role

The full conversation history, tool outputs, and file states are all restored. Claude picks up exactly where it left off.

Multiple Sessions for Multiple Repos

When working across repos, run separate Claude sessions:

# Terminal 1 -- AgnosticD
cd ~/work/code/agnosticd && claude

# Terminal 2 -- AgnosticV
cd ~/work/code/agnosticv && claude

# Terminal 3 -- Showroom
cd ~/work/showroom-content/my-workshop/ && claude

Each session has its own context. No bleed-over between repos.


Plan Mode

Plan mode lets Claude explore and design before writing code. It’s read-only – Claude can read files and search, but can’t modify anything until you approve the plan.

How to Enter Plan Mode

Cycle modes with the keyboard:

Press Shift+Tab to cycle: Normal > Auto-Accept > Plan

Or ask Claude directly:

> Plan how to add a new validation role for AAP health checks

When to Use Plan Mode

Edit Plans in Your Editor

Press Ctrl+G to open the current plan in your default editor (vim, VS Code, etc.) for direct editing.


Keyboard Shortcuts

ShortcutAction
EscStop Claude mid-action
Esc EscRewind / checkpoint menu
Shift+TabCycle modes: Normal > Auto-Accept > Plan
Ctrl+GOpen plan in your editor
Ctrl+OToggle verbose mode (see Claude's reasoning)
Option+T / Alt+TToggle extended thinking on/off
Ctrl+BBackground a running task

All Slash Commands

CommandWhat It Does
/clearWipe conversation history — start fresh
/compactSummarize conversation to free context space
/modelSwitch between Sonnet, Opus, Haiku
/renameName the current session for later resume
/resumePick from previous sessions to continue
/rewindUndo Claude's last changes (code + conversation)
/initGenerate a CLAUDE.md for the current repo
/memoryView/edit persistent project memory
/costCheck token usage and cost (API users)
/contextSee context window usage
/configOpen Claude Code settings
/hooksConfigure automated checks
/helpShow all available commands

</div>


Extended Thinking

Extended thinking gives Claude more time to reason through complex problems before responding. Toggle it with Option+T (Mac) or Alt+T (Linux).

Use extended thinking when:

ℹ️
Note: Extended thinking uses more tokens and is slower. Don't leave it on for simple tasks like file edits or running commands.

Hooks

Hooks run shell commands automatically before or after Claude performs actions. Use them to enforce standards without remembering to ask.

Example: Auto-lint YAML After Every Edit

Add to .claude/settings.json in your AgnosticV repo:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "yamllint -d relaxed \"$TOOL_INPUT_FILE_PATH\" 2>&1 || true"
          }
        ]
      }
    ]
  }
}

Every time Claude edits or creates a file, yamllint runs automatically. Claude sees the lint output and fixes issues without you asking.

Example: Block Destructive Git Commands

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "echo \"$TOOL_INPUT\" | grep -qE 'push --force|reset --hard|clean -f' && echo 'Blocked: destructive git command' >&2 && exit 2 || exit 0"
          }
        ]
      }
    ]
  }
}

RHDP Skills Usage

Available Skills

SkillWhat It DoesUse When
/showroom:create-labGenerate a workshop module with AsciiDocBuilding hands-on lab content
/showroom:create-demoCreate a Know/Show demo moduleBuilding presenter-led demos
/showroom:verify-contentRun quality checks on Showroom contentBefore submitting a PR
/showroom:blog-generateConvert workshop/demo into a blog postRepurposing content
/agnosticv:catalog-builderCreate/update AgV catalog filesNew catalog items or updates
/agnosticv:validatorValidate AgV catalog configsBefore submitting AgV PRs
/health:deployment-validatorCreate Ansible validation rolesBuilding RHDP health checks

Getting Better Output from Skills

The most common complaint is that skills produce generic content. Here’s how to fix that.

Always provide a reference module:

> Read @content/modules/ROOT/pages/module-01.adoc for the style,
> tone, and AsciiDoc patterns. Now create module-02 following
> the exact same structure.

Be specific about what you want:

# Bad -- produces generic content
> /showroom:create-lab

# Good -- Claude knows exactly what to generate
> /showroom:create-lab
> Workshop topic: Migrating VMs from VMware to OpenShift Virtualization
> This module covers the MTV operator. Target audience: infrastructure
> admins familiar with VMware but new to OpenShift.
> Reference: @content/modules/ROOT/pages/module-01.adoc

For AgnosticV, know your mode:

The catalog-builder skill offers 4 modes. Choose the right one:

  1. Full Catalog – new catalog item from scratch
  2. Common.yaml Only – updating deployment config
  3. Description.adoc Only – updating the RHDP listing page
  4. Info Message Only – updating the post-deployment info page


End-to-End Workflows

New Workshop from Scratch

When building a new workshop, the sequence and session isolation matter.

Step 1: Create Showroom content (Terminal 1)

cd ~/work/showroom-content/my-new-workshop-showroom && claude
> /rename showroom-new-workshop
> /showroom:create-lab

Generate Module 1 with your reference materials. Then for Module 2+, always reference the previous module:

> Read @content/modules/ROOT/pages/module-01.adoc for the style
> and patterns. Now create module-02 covering job templates.

Step 2: Verify Showroom content (same terminal)

> /showroom:verify-content

Fix any issues before moving on.

Step 3: Create AgV catalog item (Terminal 2)

cd ~/work/code/agnosticv && claude
> /rename agv-new-workshop
> /agnosticv:catalog-builder

Choose Mode 1 (Full Catalog). Point it to your new Showroom repo.

Step 4: Validate and PR (each terminal)

# In AgnosticV terminal
> Run yamllint on common.yaml. Fix any issues. Commit and create PR.

# In Showroom terminal
> Commit all modules. Create PR.
⚠️
Key discipline: Finish each repo's work in its own session before moving to the next. Don't switch between repos in a single session -- that's where context bleed happens.

Updating an Existing Catalog Item

> Read @sandboxes-gpte/AAP_WORKSHOPS/aap-selfserv-intro/common.yaml
> The collection URL is wrong. Change it to
> https://github.com/rhpds/aap-selfserv-collection
> Run yamllint after the change.

Always read first, state the change, ask for validation. One prompt, one task.


RHDP Power Tips

These are things that aren’t documented elsewhere but matter daily.

AsciiDoc Copy-Paste Commands in Showroom

Claude consistently writes [source,bash] for commands. That’s wrong for Showroom – it loses the copy button and breaks variable substitution. The correct block syntax is:

[source,bash,role=execute,subs=attributes+]
----
 oc get pods -n %user%-project
----

Without role=execute, no copy button in the Showroom UI. Without subs=attributes+, %user% renders as literal text. Put this in your Showroom CLAUDE.md:

## AsciiDoc Command Blocks
Always use: [source,bash,role=execute,subs=attributes+]
Never use: [source,bash] alone

Always Check nav.adoc

Claude creates module files but often forgets to update content/modules/ROOT/nav.adoc, or updates it with the wrong path. The module exists but doesn’t appear in navigation. After generating modules, always say:

> Update nav.adoc to include module-04.adoc in the correct position

Read Before Updating

Don’t say “update the catalog item.” Say:

> Read @sandboxes-gpte/AAP_WORKSHOPS/aap-selfserv-intro/common.yaml
> and add a new collection entry for aap-selfserv-collection at
> version main.

Claude can’t update what it hasn’t read. Letting it guess the current state leads to overwrites and lost fields.

Track Multi-Day Work in CLAUDE.md

If a project spans multiple sessions, add state to your repo’s CLAUDE.md:

## Current Work
- aap-selfserv workshop: modules 1-2 done and merged
- Modules 3-5 remaining
- Catalog item created but not yet tested

This survives across sessions and gives Claude instant context, even if you forget to --resume.

The %user% Variable Drift

Showroom uses %user% for dynamic substitution. AsciiDoc natively uses {attribute} syntax. Claude drifts between them, especially after compaction. Add to your CLAUDE.md or compact instructions:

Always use %user% for variable substitution, never {user}

Common Pitfalls

Context Bleed Between Tasks

Problem: You finish an AgV catalog item, then ask Claude to write Showroom content without clearing. Claude puts YAML structures inside AsciiDoc files.

Fix: One /clear between unrelated tasks.

> /clear
> I'm working on the Showroom content for ocp-virt-admin.
> The repo is at ~/work/showroom-content/ocp-virt-admin-showroom/
> Create module 2 following the structure in module 1.

Auto-Compact Loses Your Patterns

Problem: You’re writing Module 4 of a workshop. Auto-compact fires. Suddenly Module 4 uses different heading levels, different admonition syntax, and {user} instead of %user%.

Fix: Compact proactively with focus instructions before auto-compact triggers.

> /compact Keep the AsciiDoc patterns from module-01.adoc,
> the %user% variable format, and the [NOTE] callout style.
> I still need to write modules 4 and 5.

Vague Prompts Burn Context

Problem: “Help me fix the catalog item” – Claude reads 15 files trying to figure out which one. Half your context is gone before it does anything useful.

Fix: Be specific. Reference the file. Tell Claude what “fixed” looks like.

> The common.yaml at sandboxes-gpte/AAP_WORKSHOPS/aap-selfserv-intro/
> has an incorrect collection repo URL. The URL should point to
> https://github.com/rhpds/aap-selfserv-collection. Fix it and
> run yamllint on the result.

Correcting Claude Over and Over

Problem: Claude creates feature/aap-update. You say no prefix. Claude creates fix/aap-update. You say no prefix at all. Three corrections later, context is full of failed attempts.

Fix: After two corrections on the same issue, /clear and write a single prompt with all constraints.

> /clear
> Create a branch called aap-catalog-update from main.
> Update the common.yaml to add the new collection entry.
> Run yamllint to validate.
> Commit with a clean message, NO AI attribution footer.
> Push and create a PR to main.

Not Validating Claude’s Output

Problem: Claude writes a common.yaml that looks right. You commit and push. CI fails because of a duplicate key or indentation error.

Fix: Tell Claude to validate after every change.

> Update the common.yaml. After the change, run yamllint
> and fix any issues before committing.

For Showroom content:

> /showroom:verify-content

Plugin Management

Install the RHDP Marketplace

> /plugin marketplace add rhpds/rhdp-skills-marketplace

Install Plugins

> /plugin install showroom@rhdp-marketplace
> /plugin install agnosticv@rhdp-marketplace
> /plugin install health@rhdp-marketplace

Update Plugins

> /plugin marketplace update
> /plugin update showroom@rhdp-marketplace

Check What’s Installed

> /plugin list

Test from a Branch

To test unreleased changes from the tech-preview branch:

> /install-plugin https://github.com/rhpds/rhdp-skills-marketplace#tech-preview

Test Locally

For local development with a cloned copy of the marketplace:

claude --plugin-dir ~/work/code/rhdp-skills-marketplace/showroom

Configuration Files

Settings Locations

FileScopeWhat Goes Here
~/.claude/settings.jsonGlobalDefault model, allowed tools, global hooks
.claude/settings.jsonProjectProject-specific hooks, permissions
~/CLAUDE.mdGlobalUniversal rules (git style, commit format)
CLAUDE.mdProjectRepo-specific conventions
.claude/rules/*.mdProjectAuto-loaded rules (always active in this repo)

Open Settings

> /config

Change Default Model

In ~/.claude/settings.json:

{
  "model": "claude-sonnet-4-20250514",
  "permissions": {
    "allow": ["Read", "Glob", "Grep"]
  }
}

Or use the CLI:

claude /config

RHDP Git Rules

These apply across all RHDP repos:

RuleCorrectWrong
Branch from maingit checkout -b aap-catalog-fix maingit checkout -b aap-catalog-fix dev
Short descriptive namesaap-catalog-fixfeature/aap-update
No prefixshowroom-module3feature/showroom-module3
No AI attributionClean commit messageCo-Authored-By: Claude footer
PR to maingh pr create --base maingh pr create --base dev
Lint firstyamllint common.yamlCommit without linting