███████╗██████╗ ███████╗ ██████╗████████╗ █████╗ ████████╗ ██████╗ ██████╗
██╔════╝██╔══██╗██╔════╝██╔════╝╚══██╔══╝██╔══██╗╚══██╔══╝██╔═══██╗██╔══██╗
███████╗██████╔╝█████╗ ██║ ██║ ███████║ ██║ ██║ ██║██████╔╝
╚════██║██╔═══╝ ██╔══╝ ██║ ██║ ██╔══██║ ██║ ██║ ██║██╔══██╗
███████║██║ ███████╗╚██████╗ ██║ ██║ ██║ ██║ ╚██████╔╝██║ ██║
╚══════╝╚═╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝
See Everything. Miss Nothing.
A cybersecurity scripting language built for pentesters, red teamers, and security researchers. Write recon scripts, build GUI tools, automate assessments — all in one clean language.
Feature of making GUI tools is available only for Windows for now. (CLI and TUI is for both, Mac and Linux)
Official Website --> https://spectatorlang.pages.dev/
Learn Spectator --> https://github.com/CzaxStudio/SpectatorDocs/
Example --> https://github.com/CzaxStudio/Spectator-example/
Spectator is a purpose-built scripting language for cybersecurity work. It combines the simplicity of Python with built-in security modules, a native GUI framework, and a package manager — all compiled into a single standalone binary.
## Recon a target in 5 lines
target = "scanme.nmap.org"
ips = resolve(target)
Trace("IPs: " --> join(ips, ", "))
do --> PortScan(target, 1, 1024)
do --> SSLInfo(target)
## Build a GUI pentest tool
#Import Spec.GUI
open.window({"title": "Ghost Recon", "bg": "#070b14", "accent": "#00d4aa"})
GUI.input("target", "Enter target...")
GUI.button("Scan", "run", {"color": "#00d4aa"})
GUI.output("out", {"height": 400})
GUI.on("run", func() {
t = GUI.get("target")
ips = resolve(t)
each ip : ips { GUI.print("out", " IP: " --> ip) }
})
end()
- Clean, readable syntax — no semicolons, no boilerplate
- Variables, maps, lists, f-strings, string concatenation (
-->) - Functions, recursion, closures, anonymous functions
if / elseif / else,loop,each,match,try/catch- Goroutines via
spawn,# runner<?>shell execution - Dot notation for maps:
person.name = "Alice" - Import libraries:
#Import coffee
| Module | Commands |
|---|---|
| Recon | Recon, PortScan, DNSLookup, BannerGrab, PingCheck, CIDRScan |
| OSINT | WHOIs, GeoIP, IPInfo, SubdomainEnum, SubTakeover |
| Web | HTTPProbe, Headers, TechDetect, SSLInfo, HeaderAudit |
| Exploitation | CORSTest, OpenRedirect, SQLiTest, CMDInject, PathTraversal |
| Fuzzing | DirBust, FuzzURL, EmailHarvest |
| Payloads | PayloadGen(xss/sqli/ssrf/lfi/cmd/ssti/xxe/redirect/nosql/ldap) |
| Crypto | HashIdentify, Crack, CipherSolve, SecretScan |
| Encoding | Encode/Decode(url/b64/html/hex/unicode/rot13/double_url) |
| Hashing | md5, sha1, sha256, base64enc, base64dec |
Full HTTP client built in — sessions, fuzzing, multi-request, extraction:
resp = http("GET", "https://target.com", {"timeout": 5000, "follow": true})
Trace(httpStatus(resp))
Trace(httpHeader(resp, "server"))
Trace(extractTitle(httpBody(resp)))
emails = extractEmails(httpBody(resp))
Build real desktop security tools — no web framework, no Electron, no Python:
open.window({"title": "My Tool", "bg": "#0a0f1a", "accent": "#38bdf8"})
GUI.sidebar([{"id": "scan", "label": "Scanner", "icon": "⌖"}])
GUI.header("Scanner")
GUI.input("target", "Enter target...")
GUI.button("Run", "scan", {"color": "#38bdf8"})
GUI.output("out", {"height": 400})
GUI.on("scan", func() { GUI.print("out", "Scanning " --> GUI.get("target")) })
end()
All GUI widgets:
label · input · password · number · button · iconButton · link · checkbox · toggle · radio · dropdown · slider · progress · spinner · output · table · image · card · badge · alert_box · code · tabs · sidebar · header · footer · divider · space · html
Structured pentest pipeline with HTML report generation:
m = missionStart("Web App Pentest", "target.com")
missionStage(m, "Recon")
missionFind(m, "CRITICAL", ".env exposed", "Database credentials leaked")
missionFind(m, "HIGH", "Missing HSTS", "SSL stripping possible")
missionEnd(m)
missionReport(m, "report.html")
Space get coffee Install a library (SHA-256 verified)
Space get ghost Install Ghost OSINT library
Space verify coffee Verify installed file integrity
Space hash mylib.str Compute SHA-256 of a library file
Space registry Browse all published libraries
Space make lib = mylib.str Package and publish your own library
Every library install is SHA-256 verified against the central registry — supply-chain attacks blocked by default.
Download the pre-built binary for your platform from Releases:
| Platform | File |
|---|---|
| Windows 64-bit | Spectator.exe |
| Linux 64-bit | spectator-linux |
| macOS Intel | spectator-mac |
| macOS Apple Silicon | spectator-mac-arm |
# Windows — run any script
./Spectator.exe run hello.str
# Linux / macOS
chmod +x spectator
./spectator run hello.strRequires Go 1.22+:
git clone https://github.com/CzaxStudio/Spectator
cd Spectator
# Build without GUI (pure terminal)
go build -ldflags="-s -w" -o Spectator.exe .
# Build with GUI support (Windows)
go get github.com/jchv/go-webview2
go mod tidy
go build -tags gui -ldflags="-s -w" -o Spectator.exe .
# Build with GUI support (Linux — requires libgtk-3-dev libwebkit2gtk-4.0-dev)
go get github.com/webview/webview_go
go mod tidy
go build -tags gui -ldflags="-s -w" -o spectator .
# Build with GUI support (macOS)
go get github.com/webview/webview_go
go mod tidy
go build -tags gui -ldflags="-s -w" -o spectator .spectator run <file.str> Run a script
spectator repl Interactive REPL
spectator build <file.str> to <out> for <os> Compile to standalone binary
spectator space <command> Package manager
spectator version Show version
spectator help Full command reference
windows / win Windows 64-bit (.exe)
linux Linux 64-bit
mac / macos macOS Intel
macarm / m1 macOS Apple Silicon
linuxarm Linux ARM64 (Raspberry Pi)
win32 Windows 32-bit
freebsd FreeBSD 64-bit
target = "example.com"
ips = resolve(target)
mxs = lookupMX(target)
nss = lookupNS(target)
txts = lookupTXT(target)
Trace("[ A ] " --> join(ips, ", "))
Trace("[ MX ] " --> join(mxs, ", "))
Trace("[ NS ] " --> join(nss, ", "))
each txt : txts { Trace("[ TXT] " --> txt) }
target = Capture("Target: ")
ports = [21, 22, 23, 25, 80, 443, 3306, 3389, 8080, 8443]
svcs = portServices()
each p : ports {
if hasPort(target, p) {
Trace(" OPEN " --> str(p) --> " " --> svcs[str(p)])
}
}
url = "https://example.com"
resp = http("GET", url, {"timeout": 8000, "follow": true})
hdrs = ["strict-transport-security", "content-security-policy",
"x-frame-options", "x-content-type-options", "referrer-policy"]
each h : hdrs {
val = httpHeader(resp, h)
if val != "" { Trace("[PASS] " --> h) }
else { Trace("[FAIL] " --> h --> " missing") }
}
types = ["xss", "sqli", "ssrf", "lfi", "cmd"]
each t : types {
Trace("── " --> upper(t) --> " ──")
payloads = payloadList(t)
each p, idx : payloads {
if idx < 5 { Trace(" [" --> str(idx+1) --> "] " --> p) }
}
}
m = missionStart("API Security Assessment", "api.target.com")
missionStage(m, "Discovery")
missionFind(m, "INFO", "API v2 detected", "REST API on port 443")
missionNote(m, "Swagger docs found at /api/docs")
missionStage(m, "Vulnerabilities")
missionFind(m, "CRITICAL", "JWT None Algorithm", "Auth bypass via alg:none")
missionFind(m, "HIGH", "IDOR in /users/{id}", "Access any user account")
missionFind(m, "MEDIUM", "Rate limiting absent", "Brute force possible")
missionEnd(m)
missionReport(m, "api_assessment.html")
Trace("Report saved.")
# Creates GhostRecon.exe — no Spectator needed to run it
spectator build ghost_recon.str to GhostRecon.exe for windows
# Cross-compile for Linux from Windows
spectator build scanner.str to scanner for linuxInstall official libraries from the Space registry:
#Import coffee
coffee_full("target.com") ## Full recon: DNS, ports, web, scoring
spectator space get coffee#Import ghost
ghost_domain("target.com") ## Domain intelligence
ghost_ip("8.8.8.8") ## IP intelligence + GeoIP
ghost_email("user@target.com") ## Email OSINT
ghost_username("target_user") ## Username enumeration across platforms
ghost_full("target.com") ## All-in-one with mission report
spectator space get ghostspectator space make lib = mylib.str # Package + generate registry entry
spectator space hash mylib.str # Get SHA-256 for registry.json
spectator space publish mylib # Show how to submit PRx = 42
name = "Spectator"
flag = true
price = 9.99
let y = "immutable-style declaration"
msg = "Hello " --> name --> "!" ## concatenation
fmsg = f"Hello {name}, you are {age}!" ## f-string
upper(name) lower(name) trim(name)
split(name, ",") join(list, "-")
contains(name, "spec") startsWith(name, "Spec")
substr(name, 0, 5) truncate(name, 20) pad(name, 30)
replace(name, "old", "new") reverse(name) repeat("*", 10)
regex("[0-9]+", text) regexMatch("^\\d+$", text)
## Lists
tools = ["nmap", "burp", "nikto"]
tools = append(tools, "gobuster")
len(tools) slice(tools, 0, 2) unique(tools)
sortList(tools) reverse(tools) tally(tools)
diff(l1, l2) intersect(l1, l2) gather([l1, l2, l3])
## Maps
info = {"host": "target.com", "port": 443}
info["proto"] = "https"
info.host ## dot notation
each val, key : info { } ## iteration
## Conditions
if score >= 90 {
Trace("A")
} elseif score >= 75 {
Trace("B")
} else {
Trace("F")
}
## Match
match status {
"open" => { Trace("port open") }
"closed" => { Trace("port closed") }
_ => { Trace("filtered") }
}
## Loops
loop 10 { Trace(_i) } ## counted (0-indexed _i)
loop { if done { break } } ## infinite + break
## Each
each item, idx : list { }
each value, key : map { }
func scan(host, port) {
if hasPort(host, port) {
return "open"
}
return "closed"
}
result = scan("target.com", 80)
## Anonymous function
checker = func(x) { return x > 0 }
## Spawn (goroutine)
spawn longScan("target.com")
try {
resp = http("GET", url, {"timeout": 3000})
} catch e {
Trace("Request failed: " --> e)
}
## Throw custom errors
throw("Target unreachable")
## Capture output
result = # runner<?whoami>
output = # runner<?nmap -sV target.com>
## Pipe commands
open_ports = # runner<?nmap -p- target> | # runner<?grep open>
## Redirect
# runner<?nmap target > /tmp/scan.txt>
writeFile("output.txt", "scan results")
appendFile("output.txt", "\nmore data")
content = readFile("output.txt")
if exists("output.txt") { Trace("file found") }
obj = {"target": "example.com", "ports": [80, 443]}
json = jsonStr(obj)
data = jsonParse(json)
Trace(data["target"])
open.window({
"title": "My Tool", ## Window title (default: "MyApp")
"width": 1200, ## Width in pixels (default: 900)
"height": 800, ## Height in pixels (default: 600)
"bg": "#070b14", ## Background color
"accent": "#00d4aa", ## Accent color (buttons, focus, progress)
"text": "#e2e8f0", ## Default text color
"font": "Segoe UI", ## Font family
"radius": "8", ## Border radius in px
"padding": "24", ## Page padding in px
"resizable": true, ## Allow window resize
"scrollbar": true, ## Show scrollbar
"css": ".g-btn { ... }" ## Inject custom CSS
})
GUI.get("id") ## Read widget value
GUI.set("id", "value") ## Set widget value
GUI.print("out_id", "text") ## Append line to output box
GUI.clear("id") ## Clear output or input
GUI.setProgress("bar", 0.75) ## Update progress bar (0.0 to 1.0)
GUI.show("id") ## Show a hidden widget
GUI.hide("id") ## Hide a widget
GUI.enable("id") ## Enable a disabled widget
GUI.disable("id") ## Disable a widget
GUI.focus("id") ## Focus an input field
GUI.setTitle("New Title") ## Change window title
GUI.setAccent("#a855f7") ## Change accent color live
GUI.setBg("#0f172a") ## Change background color live
GUI.alert("message") ## Alert dialog
GUI.confirm("message") ## Confirm dialog → returns true/false
GUI.notify("title", "body") ## Desktop notification
GUI.eval("js code") ## Run raw JavaScript
GUI.css(".sel", "prop", "val") ## Change CSS at runtime
GUI.openTab("tab_id") ## Switch to a tab
GUI.showSpinner("id") ## Show loading spinner
GUI.hideSpinner("id") ## Hide loading spinner
GUI.appendRow("table", row) ## Add row to table
GUI.clearTable("table") ## Clear all table rows
| Feature | Windows | Linux | macOS |
|---|---|---|---|
| Terminal scripts | Done | Done | Done |
| GUI apps | Done WebView2 | Done WebKitGTK | Done WKWebView |
| Standalone builds | Done | Done | Done |
| No runtime needed | Done | Done | Done |
| Cross-compilation (no GUI) | Done | Done | Done |
GUI dependencies:
- Windows — WebView2 runtime (pre-installed on Windows 10/11)
- Linux —
libgtk-3-dev libwebkit2gtk-4.0-dev(usually pre-installed) - macOS — WKWebView (built into macOS, nothing to install)
End users need nothing installed. Spectator binaries are fully self-contained.
The Space package manager handles library distribution with cryptographic integrity verification.
spectator space get <name> Install from central registry (SHA-256 verified)
spectator space get <name> <url> Install from direct URL
spectator space list Show installed libraries
spectator space registry Browse all published libraries
spectator space search <keyword> Search registry
spectator space info <name> Full details + update check
spectator space update <name> Re-download + re-verify
spectator space verify <name> Verify installed file integrity
spectator space hash <file.str> Compute SHA-256 of a file
spectator space remove <name> Uninstall
spectator space make lib = file.str Package + generate signed registry entry
spectator space publish <name> Show how to submit to central registry
- Write your library as a
.strfile - Host it publicly on GitHub
- Run
spectator space make lib = mylib.str - Run
spectator space hash mylib.str— copy the SHA-256 - Add the generated entry (with hash) to
registry.jsonvia Pull Request - Once merged — anyone on Earth can install with
spectator space get mylib
spectator/
├── lexer.go Tokenizer — converts .str source to token stream
├── parser.go Parser — builds AST from tokens
├── ast.go AST node types
├── interpreter.go Evaluator — executes the AST (177 built-in functions)
├── hacking.go Security modules — payloads, encoding, hashing, cracking
├── http_engine.go Full HTTP client — sessions, fuzzing, extraction
├── mission.go Mission pipeline + HTML report generator
├── runner.go # runner<?> shell execution engine
├── gui_windows.go GUI engine for Windows (WebView2)
├── gui_unix.go GUI engine for Linux/macOS (WebKit)
├── gui_windows_nogui.go Stub for non-GUI Windows builds
├── gui_other.go Stub for non-GUI non-Windows builds
├── space.go Space package manager
├── build.go Cross-compilation engine
├── main.go Entry point + REPL
└── colors.go ANSI color helpers
Spectator is a security research tool. Only use it on systems you own or have explicit written permission to test. Unauthorized scanning or exploitation is illegal in most jurisdictions. The authors accept no responsibility for misuse.
- Fork the repository
- Create a feature branch:
git checkout -b feature/my-feature - Commit your changes:
git commit -m "Add my feature" - Push:
git push origin feature/my-feature - Open a Pull Request
Publishing a library to the Space registry:
Open a PR adding your entry to registry.json. Include the SHA-256 hash of your hosted .str file (compute with spectator space hash mylib.str).
MIT License — see LICENSE for details.
Built by CzaxStudio
Spectator v2.0.0 — See Everything. Miss Nothing.