The Problem

I use gittype to type through open source code while I read it as I find it therapeutic. It's effective because it forces procedural learning rather than passive reading. But I had a gap: I needed the same kind of deliberate practice for security CLI tools.

Security work requires fluency with tools like nmap, tshark, Burp Suite, and Metasploit. Reading documentation helps you understand what flags do, but it doesn't build the muscle memory to type commands quickly under pressure. During penetration tests or incident response, you need commands at your fingertips, not buried in --help output or man pages.

I searched for an existing solution. Nothing matched what I needed: a lightweight drill system that would let me practice typing security commands with realistic context about what each flag does and what output to expect.

So I built Typesec.

Design Constraints

I wanted something I could use immediately without friction:

  • No installation required: Browser-based so I could practice anywhere
  • Zero dependencies: Vanilla HTML, CSS, and JavaScript to avoid maintenance overhead
  • Instant feedback: Character-level validation with visual feedback on mistakes
  • Realistic context: Each command needed to show simulated tool output so I'd learn what to expect
  • Keyboard-first: Tab to skip, Enter to advance, no mouse required

The goal wasn't to build a polished product. It was to solve my problem as quickly as possible and start drilling.

Implementation

I built typesec in a few hours and immediately started using it. The core loop is simple:

  1. Display a command from a shuffled deck
  2. User types character by character
  3. Correct characters turn green, mistakes flash red
  4. On completion, show simulated terminal output with a typewriter effect
  5. Track typing accuracy across the session

Each tool deck is a plain JavaScript file containing command objects with three parts:

{
  cmd: "nmap -sV 192.168.1.1",
  desc: "Version detection - Probes open ports to determine service and version info.",
  output: [
    { c: "dim",  t: "Starting Nmap 7.94 ..." },
    { c: "info", t: "Nmap scan report for 192.168.1.1" },
    { c: "open", t: "22/tcp  open  ssh  OpenSSH 8.9" }
  ]
}

The simulated output teaches what to expect from the real tool. Seeing "22/tcp open ssh OpenSSH 8.9" after typing nmap -sV builds the connection between command syntax and expected results.

I started with 30 nmap commands, then added Burp Suite, tshark, Metasploit, and Linux privilege escalation commands. The system now contains over 450 commands across 5 tool decks.

Why This Approach Works

Typing commands repeatedly builds procedural memory. After drilling nmap scans for 20 minutes, -sV for version detection or -p- for all ports becomes automatic. You stop thinking about syntax and focus on what you're trying to accomplish.

The simulated output adds context that pure typing drills lack. You're not just memorizing flags, you're learning what successful execution looks like. This speeds up real-world usage because you recognize when output deviates from expectations.

The browser-based design means no setup friction. I can drill for 10 minutes between tasks or during breaks without installing tools or spinning up VMs.

Current State

The project is deployed on Cloudflare Workers. It works exactly as intended for my use case: quick, focused practice sessions to build fluency with security tools.

I'm adding more tool decks (hydra, sqlmap, gobuster, netcat) as I identify gaps in my own knowledge. Each new deck takes about 30 minutes to create because the structure is simple and consistent.

The code is intentionally minimal. No frameworks, no build step, no complex state management. Just vanilla JavaScript doing exactly what it needs to do. This matches my broader philosophy about software: use the simplest solution that solves the problem, then stop.

Lessons

Building this reinforced a few principles I try to follow:

Ship quickly when the problem is clear. I knew exactly what I needed. Spending time on architecture or perfect code would have delayed actually solving my problem. I built it in a few hours and started using it immediately.

Solve your own problems first. I built this because I needed it. That meant I had perfect knowledge of the requirements and could validate effectiveness immediately. If others find it useful, that's a bonus.

Simple tools compound over time. I've now drilled hundreds of commands through typesec. That cumulative practice has made me noticeably faster with these tools in real scenarios. The tool itself is simple, but the results compound.

Why I'm Documenting This

This isn't a major project. It's a small utility that solved a specific problem. But it demonstrates something I value: identifying a gap, building a minimal solution, and using it consistently.

I document projects like this because they show how I approach problems: pragmatically, with bias toward shipping, and with focus on long-term utility rather than immediate impressiveness.