Code Exploration Skill
This skill defines how to systematically explore and document a codebase. It supports four exploration levels, each with a defined scope and required outputs. Levels can be explored standalone or chained together using Drilldown Mode for progressive, recursive exploration.
Exploration Levels at a Glance
Level Scope Use When
L1 — Repo Entire repository Onboarding, architecture review, big-picture understanding
L2 — Module A single feature module/package Understanding a domain area or planning changes to a feature
L3 — File A single source file Reviewing a class, entity, or controller before editing
L4 — Function A single function or method Debugging, tracing a specific behaviour, or understanding side effects
How to Determine the Exploration Level
Before exploring, identify the level from the user's request:
-
"How does this repo work?" → L1 Repo
-
"Walk me through the auth module" → L2 Module
-
"What does user.service.ts do?" → L3 File
-
"Explain the createOrder method" → L4 Function
If the scope is ambiguous, ask the user to confirm before proceeding.
Drilldown Mode
Drilldown Mode is a recursive exploration flow. Instead of stopping after one level, you offer the user a menu of items to explore at the next level down, and continue until they are satisfied.
The Drilldown Chain
L1 Repo └─► Discover all modules → offer menu → user picks one L2 Module └─► Discover all files → offer menu → user picks one L3 File └─► Discover all functions → offer menu → user picks one L4 Function
How to Activate
Drilldown Mode activates when the user:
-
Asks to "explore" or "walk through" the repo/module/file recursively
-
Responds to a drilldown prompt by picking an item from your menu
-
Explicitly says "go deeper", "drill into X", or "explore all modules"
Drilldown Prompt Rules
After completing any L1, L2, or L3 exploration, you MUST end your response with a Drilldown Prompt — a numbered menu of the next-level items the user can explore.
Format:
🔍 Drilldown — Pick a [module/file/function] to explore next:
auth— JWT authentication & authorizationusers— User management & profileorders— Order creation, tracking & fulfillment
Reply with a number, a name, or say "explore all" to go through each one.
"Explore All" Behaviour
If the user says "explore all", explore every item in the menu sequentially, presenting each L2/L3/L4 result one at a time.
-
After each item, ask: "Continue to the next one ([name])?"
-
Stop if the user says no or indicates they found what they needed.
Drilldown Context Tracking
Maintain a breadcrumb at the top of every drilldown response so the user always knows where they are:
📍 Repo → auth module → auth.service.ts
L1 — Repo Exploration
Goal
Give a high-level map of the entire codebase so any developer (or AI agent) can navigate it confidently.
Steps
-
Read README.md , package.json / go.mod / equivalent manifest
-
List top-level directories and infer their purpose
-
Identify the tech stack, frameworks, and key dependencies
-
Map out the major modules/packages and their responsibilities
-
Identify cross-cutting concerns (auth, logging, config, error handling)
-
Note entry points (e.g., main.ts , index.js , app.module.ts )
Required Outputs
- Repo Overview
Project: <name> Purpose: <one-sentence description> Tech Stack: <language, framework, major libs> Entry Point: <file>
- Module Map
A table or tree of all major modules and their single-line purpose:
src/ ├── modules/ │ ├── auth/ — JWT authentication & authorization │ ├── users/ — User management & profile │ └── orders/ — Order creation, tracking & fulfillment ├── common/ — Shared guards, interceptors, filters, pipes └── config/ — Environment variable validation & configuration
- Architecture Diagram
A Mermaid diagram showing how top-level modules relate to each other:
graph TD Client --> AuthModule AuthModule --> UsersModule UsersModule --> DB[(Database)] OrdersModule --> UsersModule OrdersModule --> DB
- Cross-Cutting Concerns
List shared infrastructure and where it lives:
Concern Implementation Location
Authentication JWT + Passport common/guards/jwt-auth.guard.ts
Logging Winston common/interceptors/logging.interceptor.ts
Validation class-validator main.ts GlobalValidationPipe
Error Handling Global Exception Filter common/filters/http-exception.filter.ts
- Environment / Config Dependencies
List all environment variables the repo relies on, if a config file exists:
DATABASE_URL — PostgreSQL connection string JWT_SECRET — Token signing secret ALLOWED_ORIGINS — CORS whitelist (comma-separated) REDIS_URL — Cache store connection
- Notable Observations
-
Unusual patterns, tech debt hotspots, or non-obvious conventions
-
Missing tests, absent documentation, or areas flagged for refactor
▶ Drilldown Prompt (MANDATORY)
After delivering the L1 output, list every discovered module as a numbered menu:
🔍 Drilldown — Pick a module to explore next:
auth— JWT authentication & authorizationusers— User management & profileorders— Order creation, tracking & fulfillment
Reply with a number, a name, or say "explore all" to go through each one.
L2 — Module Exploration
Goal
Fully understand a single feature module: its API surface, data flow, dependencies, and internal structure.
Steps
-
List all files in the module directory
-
Read the module definition file (e.g., *.module.ts ) to find imports/providers/exports
-
Identify controllers, services, repositories, DTOs, and entities
-
Trace which external modules this module depends on
-
Identify which modules consume this module's exports
Required Outputs
- Module Overview
Module: <name> Purpose: <what domain problem does this module solve> Key Files: <controller, service, entity, DTO files>
- API Surface (for backend modules)
A table of all exposed endpoints:
Method Route Guard Description
POST /auth/login
Public Authenticates user, returns JWT
GET /users/:id
JwtAuthGuard Fetches user profile by ID
PATCH /users/:id
JwtAuthGuard + RolesGuard Updates user profile
- Data Flow Diagram
How data moves through the module (request → response):
graph LR Client -->|HTTP Request| Controller Controller -->|DTO| Service Service -->|Entity| Repository Repository -->|SQL| DB[(Database)] DB -->|Row| Repository Repository -->|Entity| Service Service -->|Response DTO| Controller Controller -->|JSON| Client
- Dependency Map
This module IMPORTS: TypeOrmModule(User), JwtModule, ConfigModule This module EXPORTS: UsersService This module is used by: AuthModule, OrdersModule
- DTO Structure
Document all DTOs in the module, including their validation rules:
// CreateUserDto name: string @IsString @IsNotEmpty email: string @IsEmail password: string @IsString @MinLength(8) role: Role @IsEnum(Role) @IsOptional (default: 'user')
- Database / Entity Structure
Document entities with their columns, types, constraints, and relations:
User Entity (table: users) ├── id: uuid PK, generated ├── name: varchar NOT NULL ├── email: varchar UNIQUE, NOT NULL, @Index ├── password: varchar NOT NULL (hashed) ├── role: enum DEFAULT 'user' ├── createdAt: timestamp auto ├── updatedAt: timestamp auto └── orders: Order[] OneToMany → orders.userId
- Error Catalogue
List what exceptions each service method can throw:
Method Exceptions Thrown Condition
findOne(id)
NotFoundException
User does not exist
create(dto)
ConflictException
Email already registered
update(id, dto)
NotFoundException
User does not exist
- Config / Env Dependencies
List environment variables this module specifically depends on:
JWT_SECRET — Used in JwtModule.register() JWT_EXPIRES_IN — Token TTL (default: '7d')
- Test Coverage Snapshot
File Has Tests Notes
users.service.ts
✅ Yes users.service.spec.ts — 12 tests
users.controller.ts
✅ Yes users.controller.spec.ts — 6 tests
auth.service.ts
❌ No No spec file found
- Known Gotchas / Tech Debt
-
Any unusual patterns, workarounds, or TODOs noted in this module
-
Non-obvious business rules baked into service logic
▶ Drilldown Prompt (MANDATORY)
After delivering the L2 output, list every file in the module as a numbered menu:
📍 Repo → users module 🔍 Drilldown — Pick a file to explore next:
users.controller.ts— HTTP route handlersusers.service.ts— Business logicuser.entity.ts— Database entitycreate-user.dto.ts— Create request shapeupdate-user.dto.ts— Update request shape
Reply with a number, a name, or say "explore all" to go through each one.
L3 — File Exploration
Goal
Understand what a single file does, what it exports, and how it fits into the larger system.
Steps
-
Read the file fully
-
Identify its type (controller, service, entity, DTO, guard, interceptor, utility, etc.)
-
List all exported classes, functions, and constants with their purpose
-
Note injected dependencies (DI tokens)
-
Identify any DTOs or entity types used
Required Outputs
- File Overview
File: <filename> Type: <Service | Controller | Entity | DTO | Guard | Utility | ...> Purpose: <one-sentence description> Exports: <list of exported symbols>
- Class / Function Summary Table
Symbol Type Description
UserService
Class Core business logic for user management
UserService.findOne()
Method Fetches a user by ID, throws NotFoundException if absent
UserService.create()
Method Creates a new user after checking for duplicate email
UserService.update()
Method Partially updates an existing user record
- Injected Dependencies
@InjectRepository(User) — TypeORM repository for the User entity ConfigService — Reads JWT_SECRET from environment JwtService — Signs and verifies JWT tokens
- DTO / Entity Types Used
If the file uses DTOs or entities, show their shape (refer to L2 Section 5 & 6 format).
- Notable Patterns
- Any unusual design patterns, workarounds, or non-obvious logic in this file
▶ Drilldown Prompt (MANDATORY)
After delivering the L3 output, list every exported function/method as a numbered menu:
📍 Repo → users module → users.service.ts 🔍 Drilldown — Pick a function to explore next:
findAll()— Returns paginated list of usersfindOne(id)— Fetches a single user by IDcreate(dto)— Creates a new userupdate(id, dto)— Partially updates a userremove(id)— Soft-deletes a user
Reply with a number, a name, or say "explore all" to go through each one.
L4 — Function Exploration
Goal
Deeply understand a single function or method — what it does, how it does it, what can go wrong, and where it's used.
Steps
-
Read the full function body
-
Trace its execution from input to output, step-by-step
-
Search the codebase for all call sites (where this function is called)
-
Identify what it reads/writes (DB, cache, external APIs)
-
Note all exceptions it can throw
Required Outputs
- Function Overview
Function: <ClassName.methodName> or <functionName> File: <relative/path/to/file.ts> Signature: <async methodName(param: Type, ...): ReturnType> Purpose: <one-sentence description>
- Step-by-Step Execution Flow
Use a numbered list to trace what happens, in order:
- Receive
id: stringparameter - Query cache (Redis) for key
user:{id}→ if hit, return cached value - Query
userstable WHERE id = :id - If no row found → throw NotFoundException('User not found')
- Store result in cache with TTL 300s
- Return User entity
Or use a Mermaid flowchart for complex branching:
flowchart TD A[Start: findOne called] --> B{Cache hit?} B -- Yes --> C[Return cached User] B -- No --> D[Query DB] D --> E{User found?} E -- No --> F[Throw NotFoundException] E -- Yes --> G[Store in cache] G --> H[Return User]
- Side Effects
What does this function READ or WRITE beyond its return value?
Side Effect Type Target
DB read SELECT users table
Cache read GET user:{id} key
Cache write SET user:{id} key (TTL 300s)
- Exceptions Thrown
Exception Condition
NotFoundException
No user found with the given ID
InternalServerErrorException
Unhandled DB or cache error
- Call Sites (Where It's Referenced)
List every place in the codebase where this function is called:
File Line Context
users.controller.ts
34 @Get(':id') handler
auth.service.ts
67 Resolving user during token validation
orders.service.ts
112 Verifying user exists before creating order
- Related Functions
Functions that are closely related (called by, calls into, or is a sibling of this function):
-
create() — also in UserService , next step after findOne in registration flow
-
validateUser() in AuthService — calls findOne internally
Output Format Rules
-
Always start with the level header so the reader knows the scope.
-
Use tables for structured data (DTOs, endpoints, call sites, error catalogues).
-
Use Mermaid diagrams for flows, module relationships, and architectures.
-
Use code blocks for entity/DTO shapes, signatures, and config examples.
-
Keep descriptions concise — one sentence per item is enough; only elaborate when unusual.
-
Skip empty sections — if a section has no relevant data (e.g., no DTOs in a utility file), omit it instead of writing "N/A".
-
Highlight gotchas with a ⚠️ prefix so they stand out.
File Output (MANDATORY)
Every exploration result must be saved as a markdown file. Do this before presenting the result to the user.
Save Location
<repo-root>/.agent/explorations/
Naming Convention
<level><subject><YYYYMMDD>_<HHMMSS>.md
Level <level> prefix <subject>
L1 — Repo repo
repository name (e.g., my-app )
L2 — Module module
module folder name (e.g., auth )
L3 — File file
filename without extension (e.g., users.service )
L4 — Function fn
ClassName.methodName or functionName (e.g., UsersService.findOne )
Examples:
.agent/explorations/repo_my-app_20260311_090458.md .agent/explorations/module_auth_20260311_090512.md .agent/explorations/file_users.service_20260311_090530.md .agent/explorations/fn_UsersService.findOne_20260311_090548.md
File Header
Every exploration file must start with a metadata header:
Exploration: <Level> — <Subject>
Level: L1 Repo | L2 Module | L3 File | L4 Function Subject: <name> Generated: YYYY-MM-DD HH:MM:SS Breadcrumb: Repo → module → file → function
Drilldown Files
Each drilldown step saves its own separate file. Do not append drilldown results into the parent file — keep one file per exploration result.
Quick Decision Guide
User asks about the repo as a whole? → L1 Repo Exploration + Drilldown Prompt (module menu)
User asks about a feature area (auth, orders, payments)? → L2 Module Exploration + Drilldown Prompt (file menu)
User asks about a specific file? → L3 File Exploration + Drilldown Prompt (function menu)
User asks about a specific function/method? → L4 Function Exploration (terminal level — no further drilldown)
User picks from a drilldown menu? → Run the exploration at the next level down, with breadcrumb header
User says "explore all"? → Explore each menu item sequentially, confirming before each one
Scope is unclear? → Ask: "Are you looking at the full repo, a specific module, a file, or a function?"