I was tired of studying security tools from static cheatsheets, so I built ShellStack
When I started prepping for CEH and doing more CTFs, I ran into the same wall over and over: every resource for learning offensive security tools was either a wall of text in a PDF, a GitHub gist with no context, or a cheatsheet that assumed you already knew what half the flags did.
I didn't want notes. I wanted something that felt like sitting at an actual terminal — where I could browse tools, see real commands with context, and build the exact command I needed without digging through five tabs.
So I built ShellStack.
🔗 Live: https://shell-stack.vercel.app/
💻 Code: https://github.com/shlokkokk/ShellStack
What it actually does
ShellStack is a cybersecurity study platform built around one idea: learning security tools should feel operational, not passive.
- 280+ curated offensive security tools, organized into 19 categories, each with deep-dive docs — commands, common flags, when to use it, installation notes, and real examples
- Interactive command builders — instead of memorizing flag combos, you fill in a form and get a ready-to-copy command generated live
- 20 CEH-aligned learning modules, built for structured study instead of flipping through slides
- 1,000+ command cheat sheet with fast search and one-click copy
- A terminal-inspired UI that actually feels like a cyber-ops console instead of another docs site
The build
Stack: React 19, TypeScript, Vite, Tailwind CSS, GSAP, React Router, Radix UI primitives
A few things I focused on:
Search that actually ranks results. Early on, tool search was just naive string matching, which meant typing "nmap" could bury the actual Nmap entry under ten unrelated tools that happened to mention it in a description. I rebuilt it to weight exact and prefix matches higher, so the tool you're looking for shows up first, not buried on page 3.
Command builders that don't feel like a form. The tricky part wasn't the UI, it was designing a data model that could represent wildly different tools (a text-flag-heavy tool like Nmap vs. a mostly-positional-args tool) without a special case for every single one. Each tool's builder config lives in its own data file, so adding a new interactive tool doesn't mean touching the builder logic itself.
Content as data, not hardcoded pages. All 280+ tools and 20 CEH modules live in structured data files (src/data/tools/, src/data/modules/), not scattered across component files. This means the entire tool directory, cheat sheet, and CEH explorer all pull from the same source of truth — adding a new tool is a data entry, not a new component.
What's next
I'm still refining the command builder UX — it works, but I'm not 100% sure it's intuitive for someone seeing it cold. If you try it out, I'd genuinely love to know where it trips you up.
Also planning to expand the CEH module coverage and add a few more interactive builders for tools that currently only have static command references.
Try it
If you're studying for CEH, doing CTFs, or just want a faster way to look up a tool's flags without leaving your browser tab, take it for a spin:
🔗 https://shell-stack.vercel.app/
⭐ Star it on GitHub if it's useful: https://github.com/shlokkokk/ShellStack
Feedback, issues, and PRs are all welcome — this is very much a living project.
Top comments (9)
The detail that stood out is giving each tool its own builder config instead of one generalized data model for all 280 — that's the right call, since a flag-heavy tool like nmap and a mostly-positional tool don't actually share a shape, and forcing them into one schema just pushes the special-casing downstream instead of removing it. I've hit the same wall building ESLint detectors across different SDKs: a generic "any query() call" rule looks elegant until you realize pg and Prisma need genuinely different pattern matching, and the abstraction just relocates the mess. Curious how you're handling tools with subcommands that each carry their own flag set, like git or docker — same config shape, or does that need a third pattern?
Thanks man! Really appreciate the kind words. That ESLint analogy is so spot on — "relocates the mess" is the exact phrase for what happens when you try to over-engineer a single schema for everything haha.
For tools with subcommands like docker or git, we actually didn't need to invent a 3rd pattern! We kept it simple by either splitting complex subcommands into focused separate builders or using a subcommand selector paired with a TS generator function under the hood.
Delegating string assembly to code instead of forcing a massive JSON DSL saved us from a ton of bloat.
Would love to hear how you ended up solving that ESLint pattern matching issue in the end! Feel free to reach out or connect on LinkedIn or discord or something if you ever want to chat more architecture.
280 tools is a big enough surface that staleness seems like the real long-term risk rather than initial coverage, offensive tools get new flags and deprecate old ones constantly (nmap alone has had scan-technique and timing changes across versions). Since everything lives in structured data files rather than hardcoded pages, have you thought about how you'll catch drift between a tool's actual current CLI and what's in ShellStack's data, something like periodically diffing against the tool's own --help output? That seems like the difference between this staying trustworthy for CTFs versus slowly turning into the same kind of stale cheatsheet it was built to replace.
Man, 100% agree. Nothing worse than pulling a command in a CTF only to realize the flag was deprecated 2 versions ago!
Storing the tool catalog in structured TypeScript data modules (src/data/tools/) was step one to solve this. Because it's structured data, we can build a script to parse tool --help or man pages in a Kali environment and run automated diffs against our dataset in GitHub Actions.
Thanks for bringing this up, adding automated CLI drift checks to the roadmap!
That's a great initiative—interactive learning really helps internalize security concepts. Have you considered adding scenarios that simulate container escapes or GPU-based side-channel attacks? At work, we often deal with secure GPU execution, and tools like VoltageGPU help isolate workloads, but there's always more to learn through hands-on practice.
Thanks a lot! I really like that idea. Simulated scenarios and mini-labs are definitely something I've been thinking about—they'd make the jump from reading commands to actually understanding them much smoother. GPU/container escape scenarios would be a fun direction to explore too. Really appreciate you checking it out!
Static cheatsheets definitely lack the contextual feedback needed to truly understand how security tools behave under different edge cases. Building an interactive environment for this is a great approach, though handling the real-time stream of shell outputs back to a React frontend usually introduces some complex state management challenges. I am curious about the backend architecture you chose for ShellStack, specifically how you are handling process isolation to prevent sandbox escapes when users execute arbitrary commands.
Some comments may only be visible to logged-in visitors. Sign in to view all comments.