- Knowledge
- technology
- OOP
- Tips
- Programming
- Tips
- Tutorial
- SEO
- Ranking
- Knowledge
- Special Day
- Seo
- Bug
- Data science
- Seo
- artificial intelligence
- Machine Learning
- Robotics
- happyNewYear2021
- newYearEve
- 2021
- Automation
- Smart Home
- Career
- Best Practices
- Git
- Logging
- Web Fundamentals
- DNS
- HTTPS
- Performance
- AI Tools
- ChatGPT
- Claude
- Gemini
- Laravel
- Eloquent
- MySQL
- HTTPS
- TLS
- Web Security
- Certificates
- Developer Life
- Debugging
- Docker
- DevOps
- Transactions
- Queues
- LLMs
- AI
- AI Coding
- Developer Tools
- React Native
- Expo
- Kate PMS
- Mobile Apps
- Laravel
- Authentication
- Sanctum
- Cookies
- API Design
- Payments
- Idempotency
- DeepSeek
- Open Source AI
- LLMs
- AI News
- Git
- Version Control
- AI Coding
- Prompting
- PHP
- Checklist
- MCP
- AI Agents
- OpenAI
- Architecture
- Microservices
- Modular Monolith
- Estimation
- Developer Life
- Project Planning
- Humour
- OAuth
- OpenID Connect
- Authentication
- Embeddings
- Vector Search
- RAG
- pgvector
- OpenAI
- GPT-4.1
- Codex CLI
- Events
- Testing
- Clean Code
- Maintainability
- Code Review
- Webhooks
- API
- Security
- Claude Code
- Workflow
- AI
- LLM
- Prompt Injection
- Mobile
- React
- Networking
- TCP
- UDP
- HTTP/3
- CLAUDE.md
- AWS
- Cloud Security
- Backups
- PHPUnit
- Software Engineering
- Leadership
- Communication
- RAG
- Embeddings
- AI Engineering
- IT Infrastructure
- Networking
- Access Control
- CI/CD
- GitHub Actions
- Gemini CLI
- Claude Code
- JavaScript
- Async/Await
- Node.js
- Promises
- Security
- Cryptography
- Passwords
- MySQL
- Database
- Vibe Coding
- Software Quality
- DNS
- Code Reading
- Onboarding
- Productivity
- Background Jobs
- Developer Humour
- Estimates
- Dev Life
- JWT
- o3-mini
- DeepSeek R1
- Rate Limiting
- Kate PMS
- E-Signing
- Audit Trail
- REST
- GraphQL
- API Design
- Laravel 12
- Upgrade Guide
- Open Source
- Self-Hosting
- Task Scheduling
- Cron
- Secrets
- CORS
- PHP
- PHP-FPM
- OPcache
- GitHub Copilot
- Software Architecture
- Engineering
- TypeScript
- JavaScript
- Type Safety
- AI Security
- React Native
- Product Design
- AI Agents
- Kiro
- Queues
- Redis
- RabbitMQ
- AWS SQS
- Nginx
- Apache
- GPT-5
- gpt-oss
- Clean Code
- Architecture
- Naming
- Documentation
- Career
- ADR
- Teamwork
- Supply Chain
- Kate HRM
- HR Software
- Permissions
- System Design
- Pagination
- SSH
- Linux
- Big O
- Databases
- Laravel Boost
- MCP
- Developer Skills
- Validation
- Databases
- Indexes
- Code Quality
- Deployment
- Developer Humour
- Feature Flags
- Code Review
- Pull Requests
- Docker
- Cursor
- Authorization
- RBAC
- Gemini
- Long Context
- PHP 8.4
- Caching
- Dependency Injection
- Web Performance
- Browser
- CSS
- Database
- Migrations
- ChatGPT
- AI for Developers
- Monitoring
- On-Call
- REST
- Backend
- SQL
- NoSQL
- Database Design
- Coding Agents
- Claude 4
- API Resources
- REST API
- Load Balancing
- Scaling
- AWS
- AI Tools
- Claude
- Sora 2
- CTE
- 2FA
- TOTP
- Programming Languages
- Prompts
- Developer Workflow
- API Gateway
- APIs
- Passport
- API Auth
- Learning
- Burnout
- Developer Growth
- Web Development
- SEO
- Kate Mall
- ChatGPT Atlas
- Agent Skills
- Middleware
- Laravel 12
- Collections
- Context Window
- Monitoring
- Commit Messages
- Self Review
- Growth
- Regex
- Programming Basics
- Text Processing
- Database Design
- Normalization
- Linux
- Server Security
- Linux Foundation
- Open Standards
- Legacy Code
- Documentation
- AI Workflow
- File Uploads
- Test Data
- Hashing
- Performance
- Caching
- Enums
- Scope Creep
- Estimation
- Codex
- Gemini CLI
- Timezones
- Carbon
- Bugs
- PHP 8.5
- Gemini 3
- GPT-5.1
- Data Integrity
- Event Loop
- Async
- Opus 4.5
- AI Models
- React
- Forms
- Frontend
- Backups
- AI Images
- DALL-E
- Midjourney
- Race Conditions
- Concurrency
- Legacy Code
- Refactoring
- Senior Engineer
- Scope
- LLM
- CDN
- Web
- Sub-Agents
- Soft Deletes
- Audit Log
- Concurrency
- AI Learning
- NestJS
- AI Evals
- Policies
- SPF DKIM DMARC
- Unicode
- UTF-8
- Knowledge Graph
- Value Objects
- Technical Debt
- Feature Flags
- Laravel Pennant
- Deployment
- Copilot
- Composer
- Dependencies
- Artisan
- Automation
- AWS S3
- Object Storage
- Cloud
- Small Language Models
- Ollama
- Production
- Sessions
- HTTP
- Mentoring
- SQL
- Virtual Machines
- Web Development
- HTTP/2
- QUIC
- Web Performance
- AI Integration
- LLM API
- SOLID
- OOP
- Hosting
- Serverless
- Merge Conflicts
- Temperature
- AI Development
- Reverse Proxy
- Nginx
- Infrastructure
- Verification
- Passkeys
- WebAuthn
- Teams
- Communication
- Stakeholders
- Monorepo
- CI/CD
- Versioning
- JSON Schema
- Livewire
- Inertia
- Meetings
- Distributed Systems
- Privacy
- Full-Stack
- T-Shaped Skills
- Money
- Notifications
- Web Security
- HTTP Headers
- CSP
- Function Calling
- Load Testing
- k6
- Data Extraction
- Debugging
- WebSockets
- SSE
- Real-Time
- Laravel Reverb
- Infrastructure as Code
- Terraform
- Side Projects
- Laravel Pint
- OpenAPI
- Swagger
- UX
- Multimodal
- Jest
- Pair Programming
- APIs
- Rate Limiting
- Resilience
- Dev Humour
- Design Tokens
- JWT
- API Keys
- Sessions
- PHPStan
- Rector
- Incidents
- Reporting
- Dashboards
- Zero Trust
- IAM
- Search
- Laravel Scout
- Junior Developers
- Mentoring
- Images
- WebP
- AVIF
- Bug Reports
- Let's Encrypt
- Design Docs
- Software Design
- Observers
- Replication
- Accountability
- Data Structures
- Reliability
- LLM Memory
- Error Handling
- Payments
- Payment Gateway
- Webhooks
- PCI DSS
- Observability
- OpenTelemetry
- Personal Brand
- Writing
- Conventions
- Dates
- Scheduling
- Disaster Recovery
- Compression
- Brotli
- Deadlines
- Developer Habits
- State Machines
- Tech Roles
- UUID
- ULID
- Horizon
- Planning
- Engineering Culture
- Ownership
- Soft Skills
- Socialite
- Cost Control
- Collations
- Unicode
- Octane
- PostgreSQL
How I Use AI to Document Legacy Code (Without Trusting It Blindly)
About Post
Every long-lived system has a folder that everyone is slightly afraid of. It works. It's been working for years. Nobody is quite sure why, the person who wrote it moved on, and the only documentation is a comment that says // don't touch this.
Documenting that kind of code used to be the task that sat at the bottom of the backlog forever: important, unglamorous, and slow. AI coding agents have changed that for me. Not because they magically understand old code, but because they're very good at the tedious part (reading everything, mapping it, drafting) and leave me free for the part that needs a human (checking it's true).
Here's the workflow I use with Claude Code, step by step, including the parts where I don't trust the AI at all.
The principle: the agent drafts, the code decides
Before the steps, the rule that shapes all of them. An AI agent reading legacy code will produce explanations that sound completely confident. Most of the time they're right. Sometimes they're a plausible story about what the code probably does, which is worse than no documentation, because people will believe it.
So every claim in the final docs has to be traceable back to code, a test, or a person who knows. The agent's job is to make that verification fast, not to replace it.
Step 1: get a map before reading any code
I don't start with "explain this file". I start with the shape of the whole thing. In Claude Code I use a knowledge-graph skill that extracts the relationships across the codebase (which classes call which, which modules depend on each other) so the agent can answer structural questions without reading every file into its context.
Then I ask for an inventory, with a strict format:
List the modules in app/ that relate to billing.
For each: purpose in one sentence, main entry points,
database tables it reads and writes, and other modules
it depends on. Cite file paths for every claim.
If you are guessing, say "unverified".
That last line matters more than anything else in the prompt. Giving the agent explicit permission to say "I'm not sure" produces far more honest output than asking it to sound authoritative.
Step 2: ask what it can't explain
This is my favourite trick. After the inventory, I ask:
What in this module is surprising, inconsistent or
unexplained? List code whose purpose you cannot
determine from the code alone.
The answers are exactly the things that need documenting: the magic number, the special case for one kind of record, the job that runs twice, the column that's written but never read. Those are also the things a new developer would trip over. The agent finds them quickly because it reads with no assumptions, which is the one advantage of having no memory of the project.
Step 3: trace the important flows end to end
Module lists explain structure. Developers usually need to know flows: what happens, in order, when something occurs. So I pick the few flows that matter most and ask the agent to trace each one:
Trace what happens from the moment a payment is recorded until the receipt is sent. List every class, job, event and table involved, in order, with file and line references.
Then I verify the trace myself by following the references. With file and line numbers in hand, this takes minutes instead of an afternoon, because I'm checking a route rather than discovering one.
The rule I don't break: the agent explains what the code does. Only a person, a commit message or a ticket can explain why. When the docs need a "why" and nobody knows, I write "reason unknown" instead of letting the AI invent one.
Step 4: write the docs where developers will find them
Once a module's map and flows are verified, the agent drafts the actual documentation. I keep it small and close to the code:
- A short
README.mdin the module folder: purpose, key classes, main flows, gotchas. - A few comments on the genuinely surprising lines, explaining why they exist (if known).
- A line in the project's
CLAUDE.mdpointing to the module docs, so future agent sessions start from the verified version instead of re-guessing.
That last point creates a nice loop. Each module I document makes every later AI session in that area faster and more accurate, because the agent reads the verified docs first.
Step 5: turn understanding into tests
Documentation describes behaviour. Tests lock it in. For legacy code with few tests, I ask the agent to write characterization tests: tests that capture what the code currently does, quirks included, without judging whether it's right.
Write PHPUnit tests that capture the current behaviour of
LateFeeCalculator, including edge cases you found.
Do not change the class. If a behaviour looks like a bug,
test the current behaviour and flag it in a comment.
Those tests do two jobs. They prove the documentation's claims are true, and they give us a safety net for the day someone finally refactors that scary folder.
Where it goes wrong (and how I catch it)
- Trusting old comments. Agents read comments and believe them. A comment from years ago may describe code that has since changed. I tell the agent to treat comments as claims to verify, not facts.
- Missing the hidden callers. Code can be triggered from places search doesn't find easily: scheduled tasks, queue jobs, event listeners, external webhooks, even a cron entry on a server. I ask specifically about each of these.
- Documenting dead code. The agent will happily write a lovely explanation of a class nothing uses. Checking for callers first saves the effort, and sometimes leads to a satisfying deletion instead.
- Too much at once. One module per session. Long sessions crowd out the details, and the quality of explanations drops.
Why this is worth doing
The real cost of undocumented code isn't the missing README. It's that every change takes longer, every new developer depends on one person's memory, and every refactor feels like defusing a bomb. Documentation used to be too slow to justify. With an agent doing the reading and drafting, and a human doing the verifying, it's become one of the most useful things I can spend an afternoon on.
If you try this, start with the module people are most afraid of. It's usually the one that needs it most.
What's your approach to documenting old code: write it as you go, schedule a big push, or wait until something breaks? I'd love to hear what actually works for other teams.

Be first to comment it...