Commands & shortcuts
| You type | What it does |
|---|---|
claude |
Start an interactive session in the current directory |
claude -p "…" |
Headless: run one prompt non-interactively and print the result (scriptable in CI) |
claude --version |
Print the installed version |
/help |
List available commands |
/init |
Generate a starter CLAUDE.md from your project |
/clear |
Start a fresh conversation (do this between unrelated tasks) |
/login |
Switch between subscription and API-key auth |
/permissions |
View and edit permission rules |
/config |
Open settings |
@path/to/File.java |
Reference a file or directory so Claude reads exactly that |
!mvn test |
Run a shell command and feed its output into the conversation |
Shift+Tab |
Cycle permission modes: default → accept-edits → plan |
Esc |
Interrupt the current turn to correct course |
| “think” / “think hard” | Ask Claude to reason longer before acting |
Permission rule patterns
Rules live in settings.json under permissions. The :* suffix matches any trailing arguments.
{
"permissions": {
"allow": ["Bash(./gradlew test:*)", "Bash(mvn verify:*)"],
"ask": ["Bash(./gradlew publish:*)", "Bash(git push:*)"],
"deny": ["Bash(rm:*)"]
}
}
- allow — safe, locally reversible: compile, test, format.
- ask — anything that reaches the outside world: publish, push, deploy.
- deny — defense-in-depth, not a security boundary. You reviewing every command is the real protection.
Where configuration lives
| File | Scope | Commit it? |
|---|---|---|
~/.claude/settings.json |
Your settings, all projects | No (it’s yours) |
~/.claude/CLAUDE.md |
Your personal preferences, all projects | No |
.claude/settings.json |
Project settings (build allow-list, hooks) | Yes — shared with the team |
.claude/settings.local.json |
Your personal project overrides | No — git-ignore it |
./CLAUDE.md |
Project memory (build commands, conventions, gotchas) | Yes |
.claude/commands/*.md |
Custom slash commands | Yes (shared vocabulary) |
.claude/skills/<name>/SKILL.md |
Skills Claude reaches for on its own | Yes |
.claude/agents/*.md |
Specialized subagents | Yes |
JUnit 4 → 5 migration map
The conversion most Java teams hit during a Spring Boot 3 upgrade (Module 6). Most rows are mechanical — the last two are not.
| JUnit 4 | JUnit 5 (Jupiter) |
|---|---|
org.junit.Test |
org.junit.jupiter.api.Test |
@Before / @After |
@BeforeEach / @AfterEach |
@BeforeClass / @AfterClass |
@BeforeAll / @AfterAll (static) |
@Ignore |
@Disabled |
@Test(expected = X.class) |
assertThrows(X.class, () -> …) |
@Test(timeout = 100) |
assertTimeout(Duration.ofMillis(100), …) |
@RunWith(SpringRunner.class) |
@ExtendWith(SpringExtension.class) or @SpringBootTest |
@RunWith(MockitoJUnitRunner.class) |
@ExtendWith(MockitoExtension.class) |
@Category |
@Tag |
org.junit.Assert.* |
org.junit.jupiter.api.Assertions.* — message argument moves to last |
@Rule / @ClassRule |
No equivalent — restructure (e.g. Testcontainers @Container, @TempDir) |
Two traps: the
Assertionsmethods take the optional failure message as the last parameter, the reverse of JUnit 4 — easy to flip silently. And@Rule/@ClassRulehave no annotation swap; they must be re-expressed (Testcontainers andTemporaryFolderare the usual culprits). Tell a migrating agent to flag these rather than guess.
Spring Boot 2.7 → 3.x landmarks
- Java 17 is the hard minimum. Raise the JDK first or nothing compiles.
javax.*→jakarta.*across persistence, validation, servlet APIs.- Spring Security:
WebSecurityConfigurerAdapteris removed →SecurityFilterChainbeans. - Auto-configuration registration:
spring.factories→META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. - Hibernate 5 → 6: dialect and mapping changes that can alter runtime behaviour — pin it with characterization tests.
Back to the curriculum, or start at Module 1.