Claude Code terminal simulator

This is a bounded teaching simulation, not Claude Code. Nothing is executed, no credential is requested or read, and no terminal transcript is written to your device.

Blueprint coverage

This surface serves these published sub-skills. The percentages come from the blueprint.

Simulated terminal

This is a simulation. It does not run Claude Code, execute input, request a credential, or send data.

This visit starts with an empty transcript. Nothing typed here is stored on this device.

  1. No simulated command has run in this visit.

Guided tasks

Task completion is neither a score nor part of any readiness signal. It only remembers your place in this ordered guide.

  1. Run /helpNot done
  2. Run /verify-triageNot done
  3. Run /clearNot done
  4. Run /compactNot done
  5. Run claude -p "Summarize this diff" --output-format jsonNot done
  6. Run claude -p "Summarize this diff" --output-format stream-json --verbose --include-partial-messagesNot done
  7. Run /simulate-hook-denialNot done

Assemble the instruction hierarchy

Assign every prepared fragment to a scope. Claude Code concatenates discovered instruction files from the filesystem root down to the working directory: managed policy, user, project, then local.

Read the dated source for the load order.

Fragment placement

Each select works with a keyboard. Every fragment remains in the composed result.

Composed result

Every selected contribution is shown in root-down load order.

managed policy

managed policy

    user

    ~/.claude/CLAUDE.md

      project

      ./CLAUDE.md

        local

        ./subdirectory/CLAUDE.md

          Conflicting instructions remain present

          Context is not enforcement

          Implemented set

          These are the only invocations this simulator can show. Other input receives an explicit “not implemented here” result; it never invents a model response.

          InvocationKindWhat this simulation showsSource
          /helpbuilt-inThe built-in help command shows help and the available commands.Read the dated source
          /clearbuilt-inClear starts a new conversation with empty context.Read the dated source
          /compactbuilt-inCompact summarizes the conversation so far and continues the same conversation.Read the dated source
          /verify-triageCustom commandFrom .claude/commands/verify-triage.md at project scope. This project command is loaded from .claude/commands/verify-triage.md at repository scope. Read the dated source
          claude -p "Summarize this diff" --output-format jsonmodePrint mode runs non-interactively, can read standard input, and exits zero on success or non-zero on failure. JSON output carries response text in the result field; --continue uses the most recent conversation and --resume <session-id> uses a specific conversation. Read the dated source
          claude -p "Summarize this diff" --output-format stream-json --verbose --include-partial-messagesmodeStream JSON emits one JSON event per line, beginning with system/init and ending with a result message. Streaming requires verbose and partial-message output. Read the dated source
          /initbuilt-inInit initializes a project with a CLAUDE.md guide.Read the dated source
          /permissionsbuilt-inPermissions manages allow, ask, and deny rules by scope.Read the dated source
          /modelbuilt-inModel switches the model and saves it as the default for new sessions.Read the dated source
          /costbuilt-inCost is an alias for the usage command.Read the dated source
          /simulate-hook-denialmodeThis simulation shows a PreToolUse hook blocking a destructive tool action before it runs.Read the dated source

          Reference components

          These components count toward the module’s coverage, but they are reference material rather than commands. They are intentionally not offered as terminal input.

          Repository worked example

          This inventory is generated from the repository files at publication time. One representative file per teaching type is open for inspection; every discovered path remains listed.

          Rules

          1 file in the inventory

          Representative source: CLAUDE.md
          # Project Claude Code instructions
          
          This is the project-level Claude Code instruction file. Claude Code composes instructions from the
          enterprise, user, project, and subdirectory levels; nearer subdirectory instructions refine the
          project rules for their subtree. This file supplies the project-level configuration and does not
          override enterprise or user policy.
          
          Follow [AGENTS.md](AGENTS.md) for the repository's content, security, test, and commit rules. Read
          [BLUEPRINT.md](BLUEPRINT.md) before changing study material. Keep lab tests keyless, use Python
          3.11+ standard-library-first code, and run `ruff check .`, `ruff format --check .`, and `pytest -q`
          after changes.
          
          Claude Opus 5, acting as the orchestrator in Claude Code, may run `git add` and `git commit`, and
          only after the full gate set passes. The permission is scoped to that model in that role: every
          delegated implementer — Codex, Antigravity, or any other CLI — leaves its work uncommitted in the
          working tree for the orchestrator to review, re-gate, and commit. [AGENTS.md](AGENTS.md) no longer
          states the older blanket prohibition, so this paragraph is the only rule on the subject rather than
          an override of a conflicting one.
          
          Use `/verify-triage` to run the triage verification sequence. Use the `triage-security` skill when
          reviewing the untrusted-input boundary, secret handling, or tool permissions.
          
          <!-- SPECKIT START -->
          The active feature is `004-item-bank-expansion`. For the technologies in use, the project structure,
          and the shell commands that verify a change, read [the implementation
          plan](specs/004-item-bank-expansion/plan.md) and [its
          quickstart](specs/004-item-bank-expansion/quickstart.md). Feature 003's
          [plan](specs/003-claude-code-domain/plan.md) describes the Claude Code module, feature 002's
          [plan](specs/002-lab-runner-mock-exam/plan.md) describes the lab runner and the mock exam, and
          feature 001's [plan](specs/001-study-site-foundation/plan.md) still describes the site's
          foundation.
          
          The site is an Astro 7 and TypeScript project in `site/`, rendering this repository's existing
          markdown in place — copying study text into `site/` fails the build. Exam figures come from
          `site/src/data/blueprint.json`, generated from `BLUEPRINT.md` by `tools/export_site_data.py`; never
          edit that file or type a weight by hand. The same rule now covers `site/src/data/mock.json` and
          `site/src/data/items.json`, generated by `tools/export_mock_data.py` and
          `tools/export_item_bank.py`.
          
          Pyodide runs `lab/` and `drills/` in a Web Worker on lab pages only, fetched after an explicit Run
          and never before; the mock exam and the quizzes are plain TypeScript over build-time data and must
          never import the runtime client. Per-domain quotas come from `drills.engine.mock.apportion_items` at
          build time — never reimplement apportionment in TypeScript. Practice items live in `drills/bank/`
          and must be original, validated by `python -m drills.engine validate`.
          
          The Claude Code module adds `site/src/data/claude-code.json`, generated by
          `tools/export_claude_code_data.py` from `claude-code/commands.yml`, this repository's own `.claude/`
          directory, and a recording of what its hook actually decides — never hand-edit it, and never write a
          sentence in `site/` describing what that hook denies. Only the configuration builder may reach the
          runtime client, through a `run-hook` message whose exit code is a decision: a hook exiting `2` is
          the hook working, not a failure. The instruction hierarchy is concatenated root-down, never
          overridden, and terminal transcripts are never written to the candidate's device.
          <!-- SPECKIT END -->
          

          Settings

          1 file in the inventory

          Representative source: .claude/settings.json
          {
            "permissions": {
              "allow": [
                "Bash(ruff check .)",
                "Bash(ruff format --check .)",
                "Bash(pytest -q)",
                "Bash(python -c:*)"
              ],
              "deny": [
                "Read(.env)",
                "Read(.env.*)"
              ]
            },
            "hooks": {
              "PreToolUse": [
                {
                  "matcher": "Write|Edit",
                  "hooks": [
                    {
                      "type": "command",
                      "command": "python \"$CLAUDE_PROJECT_DIR/.claude/hooks/prevent_destructive_actions.py\"",
                      "timeout": 5
                    }
                  ]
                },
                {
                  "matcher": "Bash",
                  "hooks": [
                    {
                      "type": "command",
                      "command": "python \"$CLAUDE_PROJECT_DIR/.claude/hooks/prevent_destructive_actions.py\"",
                      "timeout": 5
                    }
                  ]
                }
              ]
            }
          }
          

          Command

          1 file in the inventory

          Representative source: .claude/commands/verify-triage.md
          ---
          description: Run the triage lab's keyless lint, format, and test gates
          allowed-tools:
            ["Bash(ruff check .)", "Bash(ruff format --check .)", "Bash(pytest -q)"]
          ---
          
          Run these commands from the repository root, in order:
          
          1. `ruff check .`
          2. `ruff format --check .`
          3. `pytest -q`
          
          Report each command's outcome. Do not change files while this command is running; use the normal
          editing workflow to fix a failure, then invoke `/verify-triage` again.
          

          Skill

          15 files in the inventory

          Representative source: .claude/skills/triage-security/SKILL.md
          ---
          name: triage-security
          description: >-
            Use when reviewing or changing triage untrusted-input boundaries, PII redaction, output leakage
            checks, API-key handling, or tool exposure policy.
          ---
          
          # Triage security review
          
          Read `AGENTS.md`, `BLUEPRINT.md`, `lab/ingest.py`, `lab/security.py`, and `lab/secrets.py` before
          making a security change. Preserve the four layers: input inspection is a recorded signal;
          `lab.ingest` provides the nonce-bound JSON data boundary; `ToolExposurePolicy` is the capability
          boundary; output checking prevents trusted-content leakage.
          
          Do not treat pattern matching or approval as a substitute for least privilege. Untrusted tickets
          must keep read-only tool exposure even when an approval decision is present. Redact PII before logs
          or traces, resolve live credentials only from the environment, and never add a secret to fixtures,
          prompts, exception text, or documentation.
          
          Run `/verify-triage` after changes. For hook changes, also execute
          `python .claude/hooks/prevent_destructive_actions.py` with representative `PreToolUse` JSON input.
          

          Agent

          1 file in the inventory

          Representative source: .claude/agents/triage-security-reviewer.md
          ---
          name: triage-security-reviewer
          description: >-
            Use this agent to review a triage security change for untrusted-input boundaries, least-privilege
            tool exposure, PII or secret leakage, and keyless test coverage.
          model: inherit
          color: red
          tools: ["Read", "Grep", "Glob", "Bash"]
          ---
          
          Review the change without editing files. Read `AGENTS.md` and `BLUEPRINT.md` first. Inspect the
          request boundary in `lab/ingest.py`, the four security layers in `lab/security.py`, credential
          handling in `lab/secrets.py`, and tool dispatch in `lab/tools/dispatcher.py`.
          
          Report only concrete findings with file paths and concise evidence. Verify that untrusted ticket
          text cannot forge the nonce-bound closing delimiter, write tools require both trusted capability
          exposure and explicit approval, diagnostics redact PII and credentials, and tests remain keyless.
          Run the requested test subset or the complete verification gates when useful.
          

          Hook

          1 file in the inventory

          Representative source: .claude/hooks/prevent_destructive_actions.py
          #!/usr/bin/env python3
          """Deny protected-file writes and destructive shell commands from Claude Code PreToolUse hooks."""
          
          from __future__ import annotations
          
          import json
          import re
          import sys
          from pathlib import PurePath
          from typing import Any
          
          PROTECTED_FILES = frozenset({"LICENSE"})
          _DESTRUCTIVE_COMMAND = re.compile(
              r"(?:\brm\s+-[a-z]*[rf]|\brmdir\s+/[sq]|\bdel\s+/[a-z]*[sqf]|"
              r"\bremove-item\b.{0,80}\b-recurse\b|\bgit\s+reset\s+--hard\b|"
              r"\bgit\s+clean\s+-[a-z]*f|\bformat\s+[a-z]:|\bmkfs\b|\bdd\s+if=)",
              re.IGNORECASE,
          )
          
          
          def _deny(message: str) -> int:
              """Tell Claude Code that the PreToolUse action is denied, then return a failing status."""
              print(
                  json.dumps(
                      {
                          "hookSpecificOutput": {"permissionDecision": "deny"},
                          "systemMessage": message,
                      }
                  ),
                  file=sys.stderr,
              )
              return 2
          
          
          def _protected_path(value: object) -> bool:
              """Match a protected basename from a relative or absolute write path."""
              if not isinstance(value, str):
                  return False
              return PurePath(value.replace("\\", "/")).name.upper() in PROTECTED_FILES
          
          
          def _protected_file_in_command(command: str) -> str | None:
              """Return the protected filename referenced by a shell command, if any."""
              for filename in PROTECTED_FILES:
                  if re.search(rf"(?<![A-Z0-9_]){re.escape(filename)}(?![A-Z0-9_])", command, re.IGNORECASE):
                      return filename
              return None
          
          
          def decide(payload: dict[str, Any]) -> int:
              """Return the hook status code for one Claude Code PreToolUse payload."""
              tool_input = payload.get("tool_input", {})
              if not isinstance(tool_input, dict):
                  return 0
              file_path = tool_input.get("file_path")
              if _protected_path(file_path):
                  return _deny(f"Protected ground-truth file write denied: {file_path}")
              command = tool_input.get("command")
              if not isinstance(command, str):
                  return 0
              protected_file = _protected_file_in_command(command)
              if protected_file is not None:
                  return _deny(f"Protected ground-truth file write denied: {protected_file}")
              if _DESTRUCTIVE_COMMAND.search(command):
                  return _deny("Destructive shell command denied by the project safety hook.")
              return 0
          
          
          def main() -> int:
              """Parse JSON from standard input, allowing empty or malformed unrelated hook input to pass."""
              try:
                  payload = json.load(sys.stdin)
              except json.JSONDecodeError:
                  return 0
              if not isinstance(payload, dict):
                  return 0
              return decide(payload)
          
          
          if __name__ == "__main__":
              raise SystemExit(main())
          

          Supporting inventory

          Supporting and unrecognized files stay visible without being presented as teaching types.

          Documentation

          Recorded hook decisions

          Each payload and result below was captured by executing .claude/hooks/prevent_destructive_actions.py at publication time. Decision details and output are rendered from that recording.

          a write to a protected ground-truth file

          Decision
          deny
          Exit code
          2
          Payload
          {
            "tool_name": "Write",
            "tool_input": {
              "file_path": "LICENSE"
            }
          }
          Hook message
          {"hookSpecificOutput": {"permissionDecision": "deny"}, "systemMessage": "Protected ground-truth file write denied: LICENSE"}
          

          a write to an ordinary source file

          Decision
          allow
          Exit code
          0
          Payload
          {
            "tool_name": "Write",
            "tool_input": {
              "file_path": "lab/security.py"
            }
          }
          Hook message

          a destructive shell command

          Decision
          deny
          Exit code
          2
          Payload
          {
            "tool_name": "Bash",
            "tool_input": {
              "command": "git reset --hard"
            }
          }
          Hook message
          {"hookSpecificOutput": {"permissionDecision": "deny"}, "systemMessage": "Destructive shell command denied by the project safety hook."}
          

          an ordinary shell command

          Decision
          allow
          Exit code
          0
          Payload
          {
            "tool_name": "Bash",
            "tool_input": {
              "command": "python -V"
            }
          }
          Hook message

          a shell command that only mentions a protected filename

          Decision
          deny
          Exit code
          2
          Payload
          {
            "tool_name": "Bash",
            "tool_input": {
              "command": "echo LICENSE"
            }
          }
          Hook message
          {"hookSpecificOutput": {"permissionDecision": "deny"}, "systemMessage": "Protected ground-truth file write denied: LICENSE"}
          

          a malformed or empty payload

          Decision
          allow
          Exit code
          0
          Payload
          []
          Hook message

          Type to search notes, guides, study plans, cheatsheets, and the blueprint.