smite.sh is a CLI troubleshooting simulator for DevOps apprentices. You get a shell and a small Kubernetes cluster, then quests that ask you to notice what is broken and fix it. Nothing here talks to a real cluster.
Built with C++20, yaml-cpp, fmt, and readline.
git clone https://github.com/smitehq/smite.git
cd smite
make
./smite --version # smite.sh 0.2.1
./smiteA new profile starts in First Steps in Kubernetes. Run:
kubectl version
Smite completes the quest and prints the next one:
Next: Deciphering the Logs (quests kubernetes k8s_reading_logs)
Continue the guided path:
quests kubernetes k8s_reading_logs
kubectl logs backend
quests kubernetes k8s_crashloop
kubectl get pods
kubectl describe pod backend
kubectl logs backend
kubectl get secrets
kubectl create secret generic db-secret --from-literal username=admin --from-literal password=supersecret
The backend pod leaves CrashLoopBackOff. Type quests to browse further scenarios, hint if you are stuck, and quit to leave.
After that first completion, smite asks whether to keep a local post-mortem (commands, time, hints). It stays off unless you say yes. Change it later with settings telemetry enable or settings telemetry disable. Nothing is sent off the machine.
A version tag (0.2.0 or v0.2.0) publishes smite-<version>-linux-amd64.tar.gz on GitHub Releases. The archive contains the smite binary, LICENSE, README.md, and the Kubernetes quest and state YAML under src/modules/. Unpack it and run ./smite. The binary loads src/modules from beside itself. Set SMITE_DATA to that src/modules directory if you relocate the binary.
The binary links yaml-cpp, fmt, readline, and ncurses dynamically. Install those shared libraries on the machine that runs it.
The same version tag publishes smite-<version>-linux-arm64.tar.gz. The archive layout matches the amd64 build: smite, LICENSE, README.md, and the Kubernetes quest and state YAML under src/modules/. Unpack it and run ./smite. The binary loads src/modules from beside itself. Set SMITE_DATA to that src/modules directory if you relocate the binary.
The binary links yaml-cpp, fmt, readline, and ncurses dynamically. Install those shared libraries on the machine that runs it.
The same version tag publishes smite-<version>-macos-arm64.tar.gz for Apple Silicon. The layout matches the Linux archive. Unpack it and run ./smite. The binary loads src/modules from beside itself. Set SMITE_DATA to that src/modules directory if you relocate the binary.
The binary links yaml-cpp, fmt, readline, and ncurses dynamically from Homebrew (/opt/homebrew on Apple Silicon). Install them on the machine that runs it:
brew install yaml-cpp fmt readline ncursesThe same version tag publishes smite-<version>-windows-amd64.tar.gz next to the Linux and macOS archives. The layout matches: smite.exe, LICENSE, README.md, and the Kubernetes quest and state YAML under src/modules/. The executable is statically linked, so it does not need the MSYS2 DLLs. Unpack it and run smite.exe. It loads src/modules from beside itself. Set SMITE_DATA to that src/modules directory if you relocate the executable.
Clang++ with C++20, plus yaml-cpp, fmt, readline, and ncurses.
# Debian/Ubuntu
sudo apt-get install clang libyaml-cpp-dev libfmt-dev libreadline-dev libncurses-dev
# macOS
brew install yaml-cpp fmt readline ncurses
# MSYS2
pacman -S mingw-w64-x86_64-clang mingw-w64-x86_64-yaml-cpp mingw-w64-x86_64-fmt mingw-w64-x86_64-ncurses mingw-w64-x86_64-readlinemake
./smite # Linux/macOS
./smite.exe # WindowsQuest and cluster YAML are loaded from src/modules next to the binary (the make dist layout includes that tree). If you move the binary, set SMITE_DATA to the modules directory.
Player state is not stored beside the binary. Settings, readline history, and quest progress go in ~/.smite:
~/.smite/settings.yaml
~/.smite/quest_state.yaml
~/.smite/.history
Prompt: zaphod@lappy486:~$
| Command | What it does |
|---|---|
help |
List command prefixes |
modules |
List loaded modules |
quests |
Open the quest browser |
quests kubernetes |
List unlocked Kubernetes quests |
quests kubernetes <id> |
Start that quest |
hint |
Next hint for the active quest |
settings |
Show telemetry |
settings telemetry enable / disable |
Turn local post-mortems on or off |
quit |
Exit |
Shell commands: ls, cd, pwd, cat, echo, touch, chmod, nano.
&& runs a second command when the first one did not fail.
These commands are implemented. Short names work the way kubectl players type them.
kubectl version
kubectl get pods | po | pod
kubectl get nodes | no
kubectl get deployments | deployment | deploy
kubectl get services | svc
kubectl get configmaps | cm
kubectl get secrets
kubectl get events
kubectl describe pod | po <name>
kubectl describe node | no <name>
kubectl describe deployment | deploy <name>
kubectl logs <pod>
kubectl delete pod | po <name>
kubectl top pods
kubectl top nodes
kubectl create secret generic <name> --from-literal <key>=<value>
kubectl create configmap <name> --from-literal=<key>=<value>
kubectl edit deployment | deploy <name>
kubectl edit service <name>
kubectl scale deployment | deploy <name> --replicas=<n>
kubectl rollout <status|history|undo> deployment <name>
kubectl cordon <node>
kubectl uncordon <node>
Anything else that starts with kubectl is reported as not implemented. It is not a shell "command not found" error: smite knows you meant kubectl and does not emulate that subcommand yet.
Guided path for a new player:
k8s_first_steps— runkubectl versionk8s_reading_logs— runkubectl logs backendk8s_crashloop— create the missingdb-secret(see the quickstart)
Other playable scenarios cover image pull failures, probes, scaling, rollouts, services, configmaps, and node pressure. A quest file whose hints depend on commands smite does not implement yet (ingress, network policy, drain, quotas, statefulsets, and similar) is hidden from quests until that command exists.
Add a scenario as src/modules/kubernetes/quests/<id>.yaml plus a matching file under state/. Set available: false when a hint tells the player to run a command the simulator cannot perform.
| Module | Description |
|---|---|
| Shell | Everyday commands (ls, cd, cat, nano, …) against an in-memory filesystem. |
| Kubernetes | Nodes, pods, deployments, services, and the quest cluster state. |
make # debug binary
make tests # unit tests
make clean && makemake release and make dist produce a stripped binary and a tarball. The archive name follows the host: dist/smite-<version>-linux-amd64.tar.gz on x86_64 Linux, dist/smite-<version>-linux-arm64.tar.gz on arm64 Linux, dist/smite-<version>-macos-arm64.tar.gz on Apple Silicon, and dist/smite-<version>-windows-amd64.tar.gz on Windows. An Intel Mac still packages dist/smite-<version>-macos-amd64.tar.gz; that archive is not uploaded. Pushing a version tag runs make dist on ubuntu-24.04, ubuntu-24.04-arm, macos-15, and windows-2025 and uploads the four published archives to the release. Windows builds are statically linked; Linux and macOS link the libraries listed above.
PRs are welcome, especially ones that make a quest completable with the commands the hints name. C++20, RAII, and the existing module interface.
MIT. Use, modify, and smite responsibly.