Browse Source

feat: Add /plan command, vue-expert, cypress-expert, and PHP/Cypress testing

New commands:
- /plan: Persistent project planning with capture-first behavior
  - Always captures Plan Mode state before creating/updating
  - Writes to git-trackable PLAN.md
  - Pairs with /save + /load for complete session continuity

New agents:
- vue-expert: Vue 3, Composition API, Pinia, performance
- cypress-expert: E2E and component testing, custom commands, CI/CD

Updated commands:
- /test: Added PHP support (PHPUnit, Pest, Codeception) and Cypress examples
- /save, /load: Clarified non-persistence is by design, not a bug

Documentation:
- Updated README with new commands and agents
- Added "What Persists vs What Doesn't" tables
- Cited Anthropic article on long-running agents

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
0xDarkMatter 4 months ago
parent
commit
25ca4be879
7 changed files with 759 additions and 9 deletions
  1. 16 2
      README.md
  2. 191 0
      agents/cypress-expert.md
  3. 144 0
      agents/vue-expert.md
  4. 5 3
      commands/load.md
  5. 245 0
      commands/plan.md
  6. 14 3
      commands/save.md
  7. 144 1
      commands/test.md

+ 16 - 2
README.md

@@ -53,6 +53,7 @@ Then symlink or copy to your Claude directories:
 | [agent-genesis](commands/agent-genesis.md) | Generate Claude Code expert agent prompts for any technology platform. |
 | [save](commands/save.md) | Save session state before ending. Creates claude-state.json and claude-progress.md for session continuity. |
 | [load](commands/load.md) | Load session context from saved state. Shows what changed, suggests next action. |
+| [plan](commands/plan.md) | Create and persist project plans. Captures Plan Mode state and writes to git-trackable PLAN.md. |
 | [review](commands/review.md) | Code review staged changes or specific files. Analyzes bugs, security, performance, style. |
 | [test](commands/test.md) | Generate tests with automatic framework detection (Jest, Vitest, pytest, etc.). |
 | [explain](commands/explain.md) | Deep explanation of complex code, files, or concepts. Architecture, data flow, design decisions. |
@@ -81,12 +82,14 @@ Then symlink or copy to your Claude directories:
 | [bash-expert](agents/bash-expert.md) | Defensive Bash scripting, CI/CD pipelines |
 | [cloudflare-expert](agents/cloudflare-expert.md) | Cloudflare Workers, Pages, DNS, security |
 | [craftcms-expert](agents/craftcms-expert.md) | Craft CMS content modeling, Twig, plugins, GraphQL |
+| [cypress-expert](agents/cypress-expert.md) | Cypress E2E and component testing, custom commands, CI/CD |
 | [fetch-expert](agents/fetch-expert.md) | Parallel web fetching with retry logic |
 | [firecrawl-expert](agents/firecrawl-expert.md) | Web scraping, crawling, structured extraction |
 | [javascript-expert](agents/javascript-expert.md) | Modern JavaScript, async patterns, optimization |
 | [laravel-expert](agents/laravel-expert.md) | Laravel framework, Eloquent, testing |
 | [react-expert](agents/react-expert.md) | React hooks, state management, Server Components, performance |
 | [typescript-expert](agents/typescript-expert.md) | TypeScript type system, generics, utility types, strict mode |
+| [vue-expert](agents/vue-expert.md) | Vue 3, Composition API, Pinia state management, performance |
 | [payloadcms-expert](agents/payloadcms-expert.md) | Payload CMS architecture and configuration |
 | [playwright-roulette-expert](agents/playwright-roulette-expert.md) | Playwright automation for casino testing |
 | [postgres-expert](agents/postgres-expert.md) | PostgreSQL management and optimization |
@@ -101,13 +104,24 @@ Then symlink or copy to your Claude directories:
 
 These commands fill a gap in Claude Code's native session management.
 
-**The problem:** Claude Code's `--resume` flag restores conversation history, but **TodoWrite task state does not persist between sessions**. When you start fresh, your task list is gone.
+**The problem:** Claude Code's `--resume` flag restores conversation history, but **TodoWrite task state does not persist between sessions—by design**. Claude Code treats each session as isolated; the philosophy is that persistent state belongs in files you control.
+
+TodoWrite tasks are stored at `~/.claude/todos/[session-id].json` and deleted when the session ends. This is intentional.
 
 **The solution:** `/save` and `/load` implement the pattern from Anthropic's [Effective Harnesses for Long-Running Agents](https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents):
 
 > "Every subsequent session asks the model to make incremental progress, then leave structured updates."
 
-### How It Works
+### What Persists vs What Doesn't
+
+| Claude Code Feature | Persists? | Location |
+|---------------------|-----------|----------|
+| Conversation history | Yes | Internal (use `--resume`) |
+| CLAUDE.md context | Yes | `./CLAUDE.md` |
+| TodoWrite tasks | **No** | Deleted on session end |
+| Plan Mode state | **No** | In-memory only |
+
+### How `/save` + `/load` Works
 
 ```
 Session 1:

+ 191 - 0
agents/cypress-expert.md

@@ -0,0 +1,191 @@
+---
+name: cypress-expert
+description: Expert in Cypress testing for E2E and component testing. Covers test architecture, selectors, custom commands, fixtures, network stubbing, CI/CD integration, and best practices for React, Vue, and Angular applications.
+model: sonnet
+---
+
+# Cypress Testing Expert Agent
+
+You are a Cypress testing expert specializing in end-to-end testing, component testing, test architecture, and CI/CD integration.
+
+## Core Capabilities
+
+- E2E test design and implementation
+- Component testing for React, Vue, Angular, Svelte
+- Custom commands and reusable utilities
+- Network request stubbing and interception
+- Fixtures and test data management
+- Authentication and session handling
+- Visual regression testing
+- CI/CD pipeline integration
+- Cross-browser testing
+- Performance optimization
+
+## Official Documentation & Resources
+
+- [Cypress GitHub Repository](https://github.com/cypress-io/cypress)
+- [Cypress Official Documentation](https://docs.cypress.io/)
+- [Best Practices Guide](https://docs.cypress.io/app/core-concepts/best-practices)
+- [Component Testing](https://docs.cypress.io/guides/component-testing/getting-started)
+- [E2E Testing Your App](https://docs.cypress.io/app/end-to-end-testing/testing-your-app)
+- [Network Requests](https://docs.cypress.io/guides/guides/network-requests)
+- [Custom Commands](https://docs.cypress.io/api/cypress-api/custom-commands)
+- [Configuration](https://docs.cypress.io/guides/references/configuration)
+- [Cypress Real World App](https://github.com/cypress-io/cypress-realworld-app)
+- [Cypress Examples](https://github.com/cypress-io/cypress-example-recipes)
+- [Cypress Blog](https://www.cypress.io/blog)
+- [Cypress Cloud](https://docs.cypress.io/guides/cloud/introduction)
+- [Testing Types](https://docs.cypress.io/app/core-concepts/testing-types)
+
+## Expertise Areas
+
+### Test Architecture
+- Page Object Model vs App Actions pattern
+- Test isolation and state management
+- Fixture organization and test data factories
+- Support file structure (commands, types, hooks)
+- Environment-specific configuration
+
+### Selectors & Queries
+- `data-cy` attribute strategy (recommended)
+- `cy.get()`, `cy.find()`, `cy.contains()`
+- Chaining and assertions
+- Retry-ability and flake prevention
+- Custom selector strategies
+
+### Network Layer
+- `cy.intercept()` for request stubbing
+- Waiting for requests with aliases
+- Response fixtures
+- GraphQL mocking
+- WebSocket testing
+
+### Authentication
+- `cy.session()` for session caching
+- Login command patterns
+- Token management
+- OAuth/SSO testing strategies
+
+### Component Testing
+- Framework-specific mounting (React, Vue, Angular)
+- Props and event testing
+- Slot/children testing
+- Store/context mocking
+- Styling verification
+
+## When to Use This Agent
+
+- Setting up Cypress in a new project
+- Designing test architecture and patterns
+- Debugging flaky tests
+- Implementing custom commands
+- Configuring CI/CD pipelines
+- Optimizing test execution time
+- Migrating from other testing frameworks
+- Component testing setup
+- Network stubbing strategies
+
+## Best Practices
+
+### Selectors
+```javascript
+// Good - use data-cy attributes
+cy.get('[data-cy=submit-button]')
+
+// Avoid - fragile selectors
+cy.get('.btn-primary')
+cy.get('#submit')
+```
+
+### Test Structure
+```javascript
+// Good - query -> query -> command/assertion
+cy.get('[data-cy=email]')
+  .type('user@example.com')
+
+cy.get('[data-cy=form]')
+  .find('[data-cy=submit]')
+  .click()
+
+// Avoid - chaining after action
+cy.get('[data-cy=submit]')
+  .click()
+  .should('be.disabled') // Don't do this
+```
+
+### Network Stubbing
+```javascript
+// Stub before visiting
+cy.intercept('GET', '/api/users', { fixture: 'users.json' }).as('getUsers')
+cy.visit('/users')
+cy.wait('@getUsers')
+```
+
+### Authentication
+```javascript
+// Use cy.session() for caching
+Cypress.Commands.add('login', (email, password) => {
+  cy.session([email, password], () => {
+    cy.visit('/login')
+    cy.get('[data-cy=email]').type(email)
+    cy.get('[data-cy=password]').type(password)
+    cy.get('[data-cy=submit]').click()
+    cy.url().should('include', '/dashboard')
+  })
+})
+```
+
+## Anti-Patterns to Avoid
+
+- Using `cy.wait(5000)` for arbitrary delays
+- Chaining commands after actions
+- Using fragile CSS selectors
+- Not using aliases for intercepts
+- Testing third-party sites
+- Sharing state between tests
+- Using `const result = cy.get(...)` (commands are async)
+- Not leveraging retry-ability
+- Skipping `baseUrl` configuration
+- Not using `data-cy` attributes
+
+## Project Structure
+
+```
+cypress/
+├── e2e/                    # E2E test specs
+│   ├── auth/
+│   │   └── login.cy.ts
+│   └── dashboard/
+│       └── overview.cy.ts
+├── component/              # Component test specs
+│   └── Button.cy.tsx
+├── fixtures/               # Test data
+│   └── users.json
+├── support/
+│   ├── commands.ts         # Custom commands
+│   ├── e2e.ts             # E2E support
+│   └── component.ts       # Component support
+└── tsconfig.json
+```
+
+## CI/CD Integration
+
+- Use `cypress run` for headless execution
+- Parallelize with Cypress Cloud
+- Record results with `--record`
+- Set up retries for flaky tests
+- Configure viewport and browser
+- Use environment variables for secrets
+
+## Performance Tips
+
+- Use `cy.session()` to cache auth state
+- Stub network requests (faster than real API)
+- Run tests in parallel
+- Use `testIsolation: false` carefully
+- Optimize fixtures (smaller payloads)
+- Disable video recording in CI if not needed
+
+---
+
+*Refer to official Cypress documentation for detailed implementation guidance.*

+ 144 - 0
agents/vue-expert.md

@@ -0,0 +1,144 @@
+---
+name: vue-expert
+description: Expert in Vue.js 3 development including Composition API, Pinia state management, Vue Router, performance optimization, and modern Vue patterns. Use this agent for Vue component architecture, reactivity system, composables, SSR/SSG with Nuxt, TypeScript integration, and Vue ecosystem best practices.
+model: sonnet
+---
+
+# Vue.js Expert Agent
+
+You are a Vue.js expert specializing in Vue 3, Composition API, state management with Pinia, performance optimization, and modern Vue development patterns.
+
+## Core Capabilities
+
+- Vue 3 Composition API and `<script setup>` syntax
+- Pinia state management (stores, getters, actions)
+- Vue Router configuration and navigation guards
+- Reactivity system (ref, reactive, computed, watch)
+- Custom composables for reusable logic
+- TypeScript integration with Vue
+- Performance optimization and lazy loading
+- SSR/SSG with Nuxt 3
+- Component design patterns and architecture
+- Testing with Vitest and Vue Test Utils
+
+## Official Documentation & Resources
+
+- [Vue.js Official Guide](https://vuejs.org/guide/introduction.html)
+- [Vue.js API Reference](https://vuejs.org/api/)
+- [Composition API FAQ](https://vuejs.org/guide/extras/composition-api-faq.html)
+- [Pinia Official Documentation](https://pinia.vuejs.org/)
+- [Vue Router Documentation](https://router.vuejs.org/)
+- [Nuxt 3 Documentation](https://nuxt.com/docs)
+- [VueUse Composables Library](https://vueuse.org/)
+- [Vue.js Style Guide](https://vuejs.org/style-guide/)
+- [Vue DevTools](https://devtools.vuejs.org/)
+- [Vue School Tutorials](https://vueschool.io/)
+- [Vue Mastery Courses](https://www.vuemastery.com/)
+- [Awesome Vue](https://github.com/vuejs/awesome-vue)
+
+## Expertise Areas
+
+### Composition API
+- `<script setup>` single-file component syntax
+- `ref()` for primitives, `reactive()` for objects
+- `computed()` for derived state
+- `watch()` and `watchEffect()` for side effects
+- `provide/inject` for dependency injection
+- Lifecycle hooks (onMounted, onUnmounted, etc.)
+- Template refs with `ref()` and `useTemplateRef()`
+
+### State Management (Pinia)
+- Store definition with `defineStore()`
+- State, getters, and actions
+- Store composition and modularity
+- Plugins and extensions
+- SSR hydration
+- DevTools integration and time-travel debugging
+- Lazy loading stores for performance
+
+### Performance Optimization
+- Component lazy loading with `defineAsyncComponent()`
+- Route-based code splitting
+- `v-memo` for expensive list rendering
+- `shallowRef` and `shallowReactive` for large objects
+- `markRaw()` for non-reactive data
+- Virtual scrolling for long lists
+- Suspense for async component loading
+- Keep-alive for component caching
+
+### Vue Router
+- Route configuration and nested routes
+- Navigation guards (beforeEach, beforeEnter)
+- Route meta fields
+- Lazy loading routes
+- Dynamic route matching
+- Scroll behavior customization
+- Route transitions
+
+## When to Use This Agent
+
+- Designing Vue 3 component architecture
+- Implementing Composition API patterns
+- Setting up Pinia stores for complex state
+- Optimizing Vue application performance
+- Migrating from Options API to Composition API
+- Integrating TypeScript with Vue
+- Building SSR/SSG applications with Nuxt
+- Creating reusable composables
+- Debugging reactivity issues
+- Configuring Vue Router for SPAs
+
+## Component Patterns
+
+### Composables (Reusable Logic)
+- Prefix with `use` (e.g., `useCounter`, `useFetch`)
+- Return refs and functions
+- Handle cleanup in `onUnmounted`
+- Accept refs as arguments for reactivity
+
+### Props and Events
+- Use `defineProps()` with TypeScript generics
+- Use `defineEmits()` for type-safe events
+- `withDefaults()` for default prop values
+- `defineModel()` for v-model bindings (Vue 3.4+)
+
+### Slots and Provide/Inject
+- Named slots for flexible composition
+- Scoped slots for data passing
+- `provide()` / `inject()` for deep prop drilling avoidance
+- Use InjectionKey for type-safe injection
+
+## Anti-Patterns to Avoid
+
+- Mutating props directly (use events instead)
+- Overusing reactive() when ref() suffices
+- Not cleaning up side effects in composables
+- Putting too much logic in components (extract to composables)
+- Using Vuex in new Vue 3 projects (use Pinia)
+- Ignoring TypeScript benefits
+- Not leveraging `<script setup>` syntax
+- Creating God components (split into smaller units)
+- Blocking renders with synchronous operations
+- Not using Vue DevTools for debugging
+
+## TypeScript Integration
+
+- Use `defineComponent()` for type inference in Options API
+- Prefer `<script setup lang="ts">` for Composition API
+- Type props with generics: `defineProps<{ msg: string }>()`
+- Type emits: `defineEmits<{ change: [id: number] }>()`
+- Use `PropType` for complex prop types
+- Leverage IDE support with Volar extension
+
+## Testing Strategies
+
+- Unit test composables in isolation
+- Use `@vue/test-utils` for component testing
+- Mock Pinia stores with `createTestingPinia()`
+- Test with Vitest for speed
+- Snapshot testing for UI consistency
+- E2E testing with Cypress or Playwright
+
+---
+
+*Refer to official Vue.js documentation for code samples and implementation details.*

+ 5 - 3
commands/load.md

@@ -8,7 +8,9 @@ Load your session context from a previous save. Reads state files, shows what's
 
 ## Why This Exists
 
-This command pairs with `/save` to implement structured session continuity. While Claude Code's `--resume` restores conversation history, it **does not restore TodoWrite task state**.
+This command pairs with `/save` to implement structured session continuity. Claude Code's `--resume` restores conversation history, but **TodoWrite task state does not persist by design**.
+
+This is intentional—Claude Code treats each session as isolated. TodoWrite tasks are stored at `~/.claude/todos/[session-id].json` and deleted when the session ends. The philosophy is that persistent state belongs in files you control.
 
 From Anthropic's [Effective Harnesses for Long-Running Agents](https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents):
 
@@ -25,9 +27,9 @@ From Anthropic's [Effective Harnesses for Long-Running Agents](https://www.anthr
 | `claude --resume` | `/load` |
 |-------------------|---------|
 | Restores conversation history | Restores task state from files |
-| Local to your machine | Portable (git-trackable) |
+| Internal storage | Git-trackable files |
+| Local to your machine | Portable across machines |
 | Automatic | Explicit (you control when) |
-| Full context | Structured summary |
 
 **Use both together**: `claude --resume` for conversation context, `/load` for task state.
 

+ 245 - 0
commands/plan.md

@@ -0,0 +1,245 @@
+---
+description: "Create, review, and persist project plans. Captures Claude Code Plan Mode state and writes to git-trackable PLAN.md."
+---
+
+# Plan - Persistent Project Planning
+
+Create, review, and update project plans. Automatically captures Claude Code's internal Plan Mode state and persists to `PLAN.md`.
+
+## Why This Exists
+
+Claude Code's native Plan Mode (Shift+Tab) is powerful for exploration, but **the plan state doesn't persist**. When your session ends, the strategic thinking is lost.
+
+This command bridges that gap:
+- **Captures** any active Plan Mode context
+- **Persists** to `PLAN.md` (git-trackable)
+- **Survives** across sessions and machines
+- **Pairs** with `/save` + `/load` for complete session continuity
+
+## Arguments
+
+$ARGUMENTS
+
+- `<goal>` - Create/update plan for a goal
+- `--review` - Display current plan
+- `--status` - Update progress on steps
+- `--capture` - Capture conversation context only (no new planning)
+- `--clear` - Archive current plan and start fresh
+
+## Default Behavior: Capture First
+
+**Every invocation of `/plan` attempts to capture internal state first.**
+
+```
+/plan <anything>
+  │
+  ├─→ Step 0: Capture internal state (ALWAYS RUNS)
+  │     ├─ Detect if Plan Mode was recently active
+  │     ├─ Extract plan-related context from conversation
+  │     ├─ Check for temp files (.claude/plan*, plan.md)
+  │     └─ Merge into working state
+  │
+  ├─→ Step 1: Check existing PLAN.md
+  │     └─ Load and parse if exists
+  │
+  └─→ Step 2: Execute requested action
+        ├─ Create new plan
+        ├─ Update existing plan
+        └─ Review/display plan
+```
+
+This ensures you never lose Plan Mode thinking, even if you forget to explicitly save.
+
+## Execution Steps
+
+### Step 0: Capture Internal State (Always)
+
+```bash
+# Check for Plan Mode artifacts
+ls -la .claude/plan* plan.md 2>/dev/null
+
+# Check conversation for plan-related discussion
+# (Analyze recent messages for: goals, approaches, decisions, steps)
+```
+
+**Extract from conversation:**
+- Goal statements ("I want to...", "We need to...")
+- Approach discussions ("Option A vs B", "We could...")
+- Decisions made ("Let's go with...", "The best approach is...")
+- Steps identified ("First... then... finally...")
+- Open questions ("Should we...", "What about...")
+
+### Step 1: Check Existing PLAN.md
+
+```bash
+# Read existing plan if present
+cat PLAN.md 2>/dev/null
+```
+
+Parse structure:
+- Current goal
+- Completed steps
+- In-progress steps
+- Pending steps
+- Open questions
+
+### Step 2: Merge and Execute
+
+Combine:
+1. Captured conversation context
+2. Existing PLAN.md content
+3. New goal/instructions from command
+
+### Step 3: Write PLAN.md
+
+```markdown
+# Project Plan
+
+**Goal**: <primary objective>
+**Created**: <timestamp>
+**Last Updated**: <timestamp>
+**Status**: In Progress | Complete | Blocked
+
+## Context
+
+<Brief description of current state and constraints>
+
+## Approach
+
+<High-level strategy chosen and why>
+
+### Alternatives Considered
+- **Option A**: <description> - <why not chosen>
+- **Option B**: <description> - <why not chosen>
+
+## Implementation Steps
+
+### Completed
+- [x] Step 1: <description>
+  - Completed: <date>
+  - Notes: <any relevant context>
+
+### In Progress
+- [ ] Step 2: <description>
+  - Started: <date>
+  - Blockers: <if any>
+
+### Pending
+- [ ] Step 3: <description>
+- [ ] Step 4: <description>
+
+## Open Questions
+
+- [ ] <question 1>
+- [ ] <question 2>
+
+## Success Criteria
+
+- [ ] <criterion 1>
+- [ ] <criterion 2>
+
+## Notes
+
+<Additional context, decisions, or observations>
+
+---
+*Plan managed by `/plan` command. Last captured: <timestamp>*
+```
+
+## Usage Examples
+
+```bash
+# Create new plan (captures any Plan Mode context first)
+/plan "Add user authentication with OAuth2"
+
+# Just capture current conversation to plan (no new analysis)
+/plan --capture
+
+# Review current plan
+/plan --review
+
+# Update progress on steps
+/plan --status
+
+# Start fresh (archives old plan)
+/plan --clear "New feature: payment processing"
+```
+
+## Workflow Integration
+
+### With Native Plan Mode
+
+```
+1. [Shift+Tab] Enter Plan Mode
+2. [Explore codebase, discuss approaches]
+3. /plan --capture              # Persist the thinking
+4. [Shift+Tab] Exit Plan Mode
+5. [Implement]
+6. /plan --status               # Update progress
+```
+
+### With /save + /load
+
+```
+Session 1:
+  /plan "Feature X"             # Strategic planning → PLAN.md
+  [work on implementation]
+  /save "Completed step 2"      # Tactical state → claude-state.json
+
+Session 2:
+  /load                         # Restore TodoWrite tasks
+  /plan --review                # See the strategy
+  [continue work]
+  /plan --status                # Update plan progress
+  /save "Completed step 3"
+```
+
+### Complete Session Continuity
+
+| Command | Captures | Persists To |
+|---------|----------|-------------|
+| `/plan` | Strategic thinking, decisions | `PLAN.md` |
+| `/save` | TodoWrite tasks, git context | `.claude/claude-state.json` |
+| `/load` | - | Restores from `.claude/` |
+
+## Flags
+
+| Flag | Effect |
+|------|--------|
+| `--review` | Display current plan without modifications |
+| `--status` | Interactive update of step progress |
+| `--capture` | Only capture conversation context, no new planning |
+| `--clear` | Archive current plan to `PLAN-<date>.md` and start fresh |
+| `--verbose` | Show detailed capture/merge process |
+
+## Output
+
+```
+🔍 Capturing internal state...
+  ✓ Plan Mode context detected (8 relevant messages)
+  ✓ Existing PLAN.md found (3 steps complete)
+  ✗ No temp plan files
+
+📋 Merging sources...
+  → Goal: "Add user authentication with OAuth2"
+  → Approach: JWT tokens with refresh rotation
+  → Progress: Steps 1-3 complete, Step 4 in progress
+
+📝 Updated PLAN.md
+
+Summary:
+  • Goal: Add user authentication with OAuth2
+  • Steps: 3 complete, 1 in progress, 2 pending
+  • Open questions: 2
+  • Success criteria: 4 defined
+
+Review with: /plan --review
+```
+
+## Notes
+
+- Always captures internal state first—you can't lose Plan Mode thinking
+- Archives old plans when using `--clear` (never destructive)
+- Works across machines if PLAN.md is committed
+- Pairs with `/save` + `/load` for complete session continuity
+- Human-readable format works without Claude Code

+ 14 - 3
commands/save.md

@@ -8,13 +8,24 @@ Save your current session state before ending work. Creates both machine-readabl
 
 ## Why This Exists
 
-Claude Code's native `--resume` flag restores conversation history, but **TodoWrite state does not persist between sessions**. When you start a new session, your task list is gone.
+Claude Code's native `--resume` flag restores conversation history, but **TodoWrite state does not persist between sessions by design**. Claude Code treats each session as isolated—the philosophy is that persistent state belongs in files you control, not in Claude's internal state.
 
-This command implements the pattern described in Anthropic's [Effective Harnesses for Long-Running Agents](https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents):
+TodoWrite tasks are stored at `~/.claude/todos/[session-id].json` and **deleted when the session ends**. This is intentional, not a bug.
+
+This command bridges the gap by implementing the pattern from Anthropic's [Effective Harnesses for Long-Running Agents](https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents):
 
 > "Every subsequent session asks the model to make incremental progress, then leave structured updates."
 
-### The Gap
+### What Persists vs What Doesn't
+
+| Claude Code Feature | Persists? | Location |
+|---------------------|-----------|----------|
+| Conversation history | Yes | Internal (use `--resume`) |
+| CLAUDE.md context | Yes | `./CLAUDE.md` |
+| TodoWrite tasks | **No** | Deleted on session end |
+| Plan Mode state | **No** | In-memory only |
+
+### The Gap `/save` Fills
 
 | Feature | Native `--resume` | `/save` + `/load` |
 |---------|-------------------|-------------------|

+ 144 - 1
commands/test.md

@@ -52,10 +52,34 @@ $ARGUMENTS
 - nose2
 ```
 
+### PHP
+```bash
+# Check composer.json for:
+- phpunit/phpunit
+- pestphp/pest
+- codeception/codeception
+- phpspec/phpspec
+- behat/behat
+
+# Check for config files:
+- phpunit.xml / phpunit.xml.dist
+- pest.php
+- codeception.yml
+```
+
+### E2E / Browser Testing
+```bash
+# Check package.json for:
+- cypress
+- playwright
+- @playwright/test
+- puppeteer
+- webdriverio
+```
+
 ### Other
 - Go: built-in testing
 - Rust: built-in testing
-- PHP: PHPUnit
 
 ## Execution Steps
 
@@ -90,6 +114,14 @@ src/utils/helper.ts → src/utils/__tests__/helper.test.ts
 app/utils/helper.py → tests/test_helper.py
                    → app/utils/test_helper.py
                    → tests/utils/test_helper.py
+
+# PHP conventions
+app/Services/UserService.php → tests/Unit/Services/UserServiceTest.php
+                             → tests/Feature/UserServiceTest.php
+
+# Cypress conventions
+src/components/Login.vue → cypress/e2e/login.cy.ts
+                        → cypress/component/Login.cy.ts
 ```
 
 ### Step 4: Generate Test File
@@ -143,6 +175,117 @@ class TestFunctionName:
         assert function_name(None) is None
 ```
 
+### PHPUnit (PHP)
+
+```php
+<?php
+
+namespace Tests\Unit\Services;
+
+use PHPUnit\Framework\TestCase;
+use App\Services\UserService;
+
+class UserServiceTest extends TestCase
+{
+    public function test_it_creates_user_with_valid_data(): void
+    {
+        $service = new UserService();
+        $user = $service->create(['name' => 'John', 'email' => 'john@example.com']);
+
+        $this->assertNotNull($user);
+        $this->assertEquals('John', $user->name);
+    }
+
+    public function test_it_throws_on_invalid_email(): void
+    {
+        $this->expectException(\InvalidArgumentException::class);
+
+        $service = new UserService();
+        $service->create(['name' => 'John', 'email' => 'invalid']);
+    }
+}
+```
+
+### Pest (PHP)
+
+```php
+<?php
+
+use App\Services\UserService;
+
+describe('UserService', function () {
+    it('creates user with valid data', function () {
+        $service = new UserService();
+        $user = $service->create(['name' => 'John', 'email' => 'john@example.com']);
+
+        expect($user)->not->toBeNull()
+            ->and($user->name)->toBe('John');
+    });
+
+    it('throws on invalid email', function () {
+        $service = new UserService();
+        $service->create(['name' => 'John', 'email' => 'invalid']);
+    })->throws(\InvalidArgumentException::class);
+});
+```
+
+### Cypress (E2E)
+
+```typescript
+describe('Login Flow', () => {
+  beforeEach(() => {
+    cy.visit('/login');
+  });
+
+  it('should login with valid credentials', () => {
+    cy.get('[data-cy=email]').type('user@example.com');
+    cy.get('[data-cy=password]').type('password123');
+    cy.get('[data-cy=submit]').click();
+
+    cy.url().should('include', '/dashboard');
+    cy.get('[data-cy=welcome]').should('contain', 'Welcome');
+  });
+
+  it('should show error with invalid credentials', () => {
+    cy.get('[data-cy=email]').type('user@example.com');
+    cy.get('[data-cy=password]').type('wrong');
+    cy.get('[data-cy=submit]').click();
+
+    cy.get('[data-cy=error]').should('be.visible');
+  });
+});
+```
+
+### Cypress (Component)
+
+```typescript
+import Login from './Login.vue';
+
+describe('Login Component', () => {
+  it('renders login form', () => {
+    cy.mount(Login);
+
+    cy.get('[data-cy=email]').should('exist');
+    cy.get('[data-cy=password]').should('exist');
+    cy.get('[data-cy=submit]').should('contain', 'Login');
+  });
+
+  it('emits submit event with credentials', () => {
+    const onSubmit = cy.spy().as('submitSpy');
+    cy.mount(Login, { props: { onSubmit } });
+
+    cy.get('[data-cy=email]').type('user@example.com');
+    cy.get('[data-cy=password]').type('password123');
+    cy.get('[data-cy=submit]').click();
+
+    cy.get('@submitSpy').should('have.been.calledWith', {
+      email: 'user@example.com',
+      password: 'password123'
+    });
+  });
+});
+```
+
 ## Usage Examples
 
 ```bash