WitFoo on Horizon

For the past six months, I've been building WitFoo's analytics platform almost entirely with Claude Code. Not as an experiment or a side project — as the primary development method for production cybersecurity software that processes billions of signals daily. Along the way, I've trained our development and support teams on these approaches and refined the workflow through hundreds of sessions and more than a few spectacular failures.

This post consolidates what I've learned, the prompts I use daily, and the hard-won lessons I've shared with my team. I hope it's useful to anyone working with AI-assisted development at scale.

The Core Philosophy: Claude Is a Disciplined Developer, Not a Chatbot

The single biggest mistake I see people make with Claude Code is treating it like a conversation. It's not. It's a developer that needs clear requirements, structured workflows, and guardrails — just like any engineer on your team. The difference is that Claude will happily go off the rails if you don't provide those guardrails, and it will do so with supreme confidence.

Every coding session at WitFoo follows a repeatable pattern: Plan → Build → Test → Document → Finalize. This isn't optional. This is what makes the difference between Claude producing useful code and Claude producing chaos.

Repository Structure: Setting Up for Success

Every Claude-ready repository needs a few key elements:

CLAUDE.md is the most important file in your repo. It's Claude's persistent memory between sessions — the "brain file" that Claude reads at session start to understand architecture, conventions, past lessons learned, and known pitfalls. I update it at the end of every session with new knowledge. Here's the critical nuance I learned recently: CLAUDE.md can cut both ways. The more data you pack into it, the more tokens it takes to initialize a session. Keep it short with references to more detailed documentation. I now finish every session with a clean-up prompt that includes "Archive any info in CLAUDE.md no longer needed."

The _prompts/ folder contains reusable prompt templates that enforce consistent workflows across sessions and developers. Our analytics repo has 26+ PR planning documents. Each one defines scope boundaries, affected components, test criteria, and acceptance conditions. This prevents Claude from inventing features you didn't ask for.

Testing scripts give Claude automated validation it can run to verify its own work. More on this below.

CURRENT_WORK.md tracks in-progress work between sessions so Claude can pick up exactly where it left off.

An _archive/ folder stores historical documentation. Never delete docs — archive them. They help Claude learn patterns from past work and assist in future troubleshooting.

The Testing Foundation

Before you write a single line of feature code with Claude, build your testing infrastructure. This was one of my earliest and most important lessons.

Create a linter.sh that enforces a strict lint policy. Create a unit-tests.sh that runs all unit tests. Create a system-tests.sh that runs all integration and system tests. Create an e2e-tests.sh that runs e2e Playwright tests or equivalent. Create utilities to interact with all machine and user endpoints. Then create a full-testing.sh that runs the entire suite. Have Claude create documentation on all these files and what they mean to your approaches.

Our full test suite takes about 90 minutes. Claude runs unit tests after every code change and the full suite before PR completion. This testing pyramid — unit tests in seconds, integration tests in minutes, E2E tests in minutes, and the full suite as the final gate — catches the majority of Claude's mistakes before they reach production.

Utilities Save Tokens (and Sanity)

If Claude needs to access the internet, scan code for changes, run tests, interact with APIs or databases, have a utility that will authenticate/connect and sanitize data before it goes into Claude. This saves dozens of tokens each session by both simplifying Claude's work and reducing the volume of ingested data.

Most of my utilities started with a prompt like: "I noticed you spent a lot of time querying the database / searching the internet / running test commands. Write a plan to create a utility that will make that easier in future sessions."

For example, our internet-research utility handles web research with a simple CLI interface: ./internet-research --query "topic" --json or ./internet-research --url "https://..." --json. Claude builds the utility, runs it via the command line, and gets clean structured data back instead of spending tokens parsing raw web content.

The Prompt Templates That Drive Everything

Here are the actual prompts I use for every development cycle. These evolved through hundreds of sessions, and I'm sharing them because I wish someone had shared theirs with me when I started.

Writing a New PR

Create a new PR in the _prompts/ folder that is optimized to be executed
by Claude Sonnet 4.5. If it should be broken into smaller sub-PR's,
do that. Review `_prompts/ENHANCE_PR.md` for guidance.

***Guidance***
Be sure to fully analyze CLAUDE.md and other documentation. Ask any
clarifying questions to have a clear understanding of intention and
success. Time is not an issue; quality is critical. The priorities are:
- Research the internet to find any new idea we might incorporate.
  Use `utils/internet-research` for all web research.
  Build it first if needed.
- Stable, secure, performant code
- Using best practices
- Aligning with the WITFOO_WAY

Ensure we use Test Driven Development and keep documentation updated.

***Tasks***
The work should address the following:
[describe your feature/task here]

The key line here is "optimized to be executed by Claude Sonnet 4.5." This tells Claude to write prompts that are clear, scoped, and machine-parseable. If the work is too large for a single session, Claude breaks it into sub-PRs automatically.

Starting PR Execution

Analyze PRx and build a plan to execute it. Be sure to fully analyze
updates to CLAUDE.md and other documentation. Ask any clarifying
questions to have a clear understanding of intention and success.
Time is not an issue; quality is critical. The priorities are:
- Research the internet to find any new idea we might incorporate.
  Use `utils/internet-research` for all web research
- Stable, secure, performant code
- Using best practices
- Aligning with the WITFOO_WAY

Ensure we use Test Driven Development and keep documentation updated.
Write the plan to ./CURRENT_WORK.md. We will use this file for
tracking tasks.

The phrase "Time is not an issue; quality is critical" is intentional. Without it, Claude tends to take shortcuts. I want it to research, think, and plan before writing a single line of code.

Closing, Committing, and Pushing

PR is now complete. Perform the following:
- Archive unneeded markdown files in `_archive` if all their
  information has been consolidated
- Update CLAUDE.md and other documentation with any updated
  information learned since the last commit
- Correct any linter errors. Include markdown linting corrections
  and any other warnings.
- Run ./scripts/unit-tests.sh and address any issues
- Clean up debug statements in the UI, system testing and e2e testing
- Remove all unneeded log files
- Archive CURRENT_WORK.md and the PR in a new folder in `_archives`
- Commit and push all changes

This prompt is essentially a checklist that ensures Claude doesn't leave a mess behind. The documentation update step is critical — future sessions benefit from everything Claude learned in this one.

Major Testing and Cleanup

All sub-PR's of PRx are complete. We need to fully test all functions
and clean up documentation.

***Work to Accomplish***
- Analyze all changes since the last commit and build a plan to ensure
  all code changes have appropriate unit, system and e2e tests
- Run e2e tests created for all sub-PR's before starting
  full-testing.sh. They may need to be re-written from sub-PR changes.
- Run scripts/full-testing.sh then review the log for any errors.
  Correct any detected issues. Note it may take 90+ minutes to complete.
- Update CLAUDE.md and other documentation
- Clean up debug statements in the UI, system testing and e2e testing
- Correct any linter errors
- Remove all unneeded log files
- Archive CURRENT_WORK.md and the PR in a new folder in `_archives`
- Commit and push all changes

Breaking Work into Phases

In build code, break into phases. This was a hard lesson. Trying to do everything in one session leads to compounding errors.

The phases that work for us: a session to build a plan for a task or PR. A separate session to build unit, system, and e2e tests. A session to begin or continue the plan, which must pass all linters and tests. A session to review for potential security issues. A session for performance testing. A session to review code and identify potential issues. Then repeat as needed.

In review and strategy phases, use Opus instead of Sonnet. Opus is better at seeing the big picture and identifying architectural issues. Sonnet is faster and cheaper for the build work. Knowing when to switch models is part of the craft.

What I Tell My Team

When I trained our development and support teams on these approaches, I distilled the lessons into a few key principles:

Claude is a tool, not magic. Structured prompts produce structured results. Freestyle prompting produces freestyle results, and not in a good way.

CLAUDE.md is your most valuable file. Keep it updated religiously. But keep it lean — point to detailed docs rather than cramming everything in.

Test everything. Claude makes mistakes. Automated tests catch them. Without a testing infrastructure, you're flying blind.

Document as you go. Future sessions and teammates benefit from captured knowledge. Every troubleshooting session should produce documentation that makes the next session faster.

Start small. One PR, one troubleshooting session at a time. Build confidence in the workflow before attempting complex multi-session work.

Archive, don't delete. Historical docs help Claude learn patterns and help you understand what went wrong when things break.

Things will come off the rails. They have many times for me, requiring reverting one or more sessions, improving scope, and trying again. The gains are worth the pains. But only if you have the testing and documentation infrastructure to recover gracefully.

The Troubleshooting Model

Beyond coding, we use Claude for systematic troubleshooting of production deployments. The approach mirrors how a senior engineer works: collect data first, analyze systematically, document findings, then execute fixes.

We use a three-phase troubleshooting workflow. First, build a troubleshooting plan by collecting metrics, analyzing support pack data, and reading CLAUDE.md for system context. Second, iterate on the plan, digging deeper into identified issues and testing remediation steps. Third, clean up by archiving troubleshooting docs, updating CLAUDE.md with new insights, and cleaning the support pack folder.

Every troubleshooting session produces a knowledge artifact that makes the next session faster. This creates a compounding knowledge base — the more you troubleshoot with Claude, the better Claude gets at troubleshooting your system.

The Honest Assessment

These approaches have reduced my token usage, improved the quality of Claude's work, and reduced the time to execute a PR. Our analytics platform — with its Go backend, Svelte frontend, Cassandra data layer, and NATS message processing — was built faster and better than I could have done alone.

But I want to be honest about the limitations. Things have come off the rails many times. Claude will confidently introduce bugs, hallucinate features you didn't ask for, and occasionally break things that were working perfectly. The testing infrastructure, documentation discipline, and phased workflow aren't optional luxuries — they're the safety net that makes AI-assisted development viable for production software.

The craft of coding with Claude is still evolving. I'm learning new lessons every week. But the foundation — structured prompts, automated testing, disciplined documentation, and a healthy skepticism of AI output — has proven solid enough to build real software on.

If you're starting your own journey with Claude Code, I hope these lessons save you some of the pain I've gone through to learn them. And if you've discovered approaches I haven't, I'd love to hear about them.


Charles Herring is co-founder and CEO of WitFoo, a cybersecurity company building collective defense solutions. He is a US Navy veteran and speaks regularly at security conferences including DEFCON, GrrCON, and Secure360. You can find him on LinkedIn.