Code Exploration
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
authmodule" → L2 Module - "What does
user.service.tsdo?" → L3 File - "Explain the
createOrdermethod" → 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:**
1. `auth` — JWT authentication & authorization
2. `users` — User management & profile
3. `orders` — 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
1. Repo Overview
Project: <name>
Purpose: <one-sentence description>
Tech Stack: <language, framework, major libs>
Entry Point: <file>
2. 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
3. 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
4. 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 |
5. 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
6. 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:**
1. `auth` — JWT authentication & authorization
2. `users` — User management & profile
3. `orders` — 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
1. Module Overview
Module: <name>
Purpose: <what domain problem does this module solve>
Key Files: <controller, service, entity, DTO files>
2. 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 |
3. 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
4. Dependency Map
This module IMPORTS: TypeOrmModule(User), JwtModule, ConfigModule
This module EXPORTS: UsersService
This module is used by: AuthModule, OrdersModule
5. 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')
6. 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
7. 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 |
8. Config / Env Dependencies
List environment variables this module specifically depends on:
JWT_SECRET — Used in JwtModule.register()
JWT_EXPIRES_IN — Token TTL (default: '7d')
9. 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 |
10. 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:**
1. `users.controller.ts` — HTTP route handlers
2. `users.service.ts` — Business logic
3. `user.entity.ts` — Database entity
4. `create-user.dto.ts` — Create request shape
5. `update-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
1. File Overview
File: <filename>
Type: <Service | Controller | Entity | DTO | Guard | Utility | ...>
Purpose: <one-sentence description>
Exports: <list of exported symbols>
2. 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 |
3. Injected Dependencies
@InjectRepository(User) — TypeORM repository for the User entity
ConfigService — Reads JWT_SECRET from environment
JwtService — Signs and verifies JWT tokens
4. DTO / Entity Types Used
If the file uses DTOs or entities, show their shape (refer to L2 Section 5 & 6 format).
5. 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:**
1. `findAll()` — Returns paginated list of users
2. `findOne(id)` — Fetches a single user by ID
3. `create(dto)` — Creates a new user
4. `update(id, dto)` — Partially updates a user
5. `remove(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
1. Function Overview
Function: <ClassName.methodName> or <functionName>
File: <relative/path/to/file.ts>
Signature: <async methodName(param: Type, ...): ReturnType>
Purpose: <one-sentence description>
2. Step-by-Step Execution Flow
Use a numbered list to trace what happens, in order:
1. Receive `id: string` parameter
2. Query cache (Redis) for key `user:{id}` → if hit, return cached value
3. Query `users` table WHERE id = :id
4. If no row found → throw NotFoundException('User not found')
5. Store result in cache with TTL 300s
6. 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]
3. 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) |
4. Exceptions Thrown
| Exception | Condition |
|---|---|
NotFoundException |
No user found with the given ID |
InternalServerErrorException |
Unhandled DB or cache error |
5. 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 |
6. Related Functions
Functions that are closely related (called by, calls into, or is a sibling of this function):
create()— also inUserService, next step afterfindOnein registration flowvalidateUser()inAuthService— callsfindOneinternally
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?"