Wavetools
wavetools is a top tier multi tool with 160 different tools
199 files · 204 MB · Python
- wavetools
- .gitattributes172 B
- .gitignore561 B
- install.bat1.2 kB
- LICENSE1.1 kB
- README.md43 kB
- requirements.txt858 B
- run.py1.0 kB
- start.bat599 B
██ ██ ▄▄▄ ▄▄ ▄▄ ▄▄▄▄▄ ██████ ▄▄▄ ▄▄▄ ▄▄ ▄▄▄▄
██ ▄█▄ ██ ██▀██ ██▄██ ██▄▄ ██ ██▀██ ██▀██ ██ ███▄▄
▀██▀██▀ ██▀██ ▀█▀ ██▄▄▄ ██ ▀███▀ ▀███▀ ██▄▄▄ ▄▄██▀
WaveTools
An animated terminal UI (TUI) toolbox for network, OSINT and everyday utility tools — with a live-reloading plugin system at its core.
Explore the architecture »
Browse the Tool Catalog
[!NOTE] WaveTools includes dual-use network, OSINT and website-recon tools (port/host scanners, subdomain/directory finders, dictionary hash/ZIP crackers). They are for authorized use only — your own systems and accounts, engagements you are contracted for, CTFs, and education. See the Security & Legal Notice.
Table of Contents
About The Project
WaveTools is an animated terminal UI (TUI), built on Textual, for security, OSINT, network, and utility tools. Every tool is driven through the same guided step-by-step flow — Banner → Description → Questions → Live Run → Result — all wrapped in a continuously animated gradient border.
The real value of WaveTools is its plugin system: tools aren't hardcoded menu entries, they're loaded at runtime from a folder. Drop a Python file with a TOOL dict and a run() function into wavetools/tools/, restart, and it shows up in the menu — categories, validation, streaming output, and result rendering all come for free.
Highlights:
- Animated TUI with selectable gradient themes, ASCII-only fallback mode, and a full onboarding wizard on first launch.
- Runtime plugin loading — native Python plugins or JSON manifests for external commands, no core changes required.
- 66 tools across Network, OSINT, Roblox, Website, Generator, Crypto and Minecraft — plus built-in System/Text utilities.
- Stable plugin API (
plugin_api) with fail-soft HTTP, file, clipboard, and browser helpers. - Reusable input folder for tokens, webhooks, cookies, proxies, and wordlists — fill fields with
Ctrl+Finstead of retyping secrets every run. - Multi-language UI — English, German, Spanish, Russian.
- Versioned plugin API with graceful compatibility/legacy handling and per-tool dependency checks.
Built With
Getting Started
Prerequisites
- Python 3.10+ (CPython). All core dependencies are pinned in
requirements.txt. - On Windows,
install.bat/start.bathandle the Python launcher detection for you.
Installation
- Get the code (clone your fork / this repository) and enter the folder
cd WaveTools - Install dependencies
On Windows you can instead double-click / runpip install -r requirements.txtinstall.bat, which finds a Python launcher, upgradespip, and installs everything for you. - Launch WaveTools
On Windows,python run.pystart.batdoes the same with launcher auto-detection.
Usage
On first launch, a one-time setup wizard walks you through language, theme, browser, ASCII mode, and folder configuration. After that, pick a category on the left, pick a tool, answer the guided questions, and watch it run.
Keybindings
Also always shown in the status bar at the bottom of the app:
| Key | Effect |
|---|---|
Enter |
Confirm selection / submit step / run tool |
↑ / ↓ |
Move selection / scroll |
← → |
Switch category |
S then Enter |
Skip the current question (uses the default) |
Esc |
Go back one step / to the menu / quit |
Ctrl+R |
Reset the tool back to its first question |
Ctrl+V |
Paste into a text field · Ctrl+C copy the result |
Ctrl+F |
Fill a text field from the input folder (when matching entries exist) |
S (main menu) |
Settings (language, theme, browser, ASCII mode, folders, editor) |
Plugin Architecture
Components at a Glance
┌──────────────────────────────────────┐
│ run.py │
│ from wavetools.core.app import main │
└──────────────────┬─────────────────────┘
│
┌───────────────────────────▼────────────────────────────┐
│ wavetools/app.py │
│ WaveToolsApp (Textual App) + all Screens │
│ Loader → Start → Main (Categories+Tools) → ToolScreen │
└───────┬───────────────────────────────┬─────────────────┘
│ │
┌────────────────▼──────────────┐ ┌────────────▼──────────────────┐
│ builtin_tools.builtin_tools()│ │ plugins.discover_all(dir, …) │
│ hardcoded built-in tools │ │ loads tools from ./tools/ │
│ (System, Utility, Faker, …) │ │ • *.py → Python plugin │
└────────────────┬──────────────┘ │ • *.json → external command │
│ └────────────┬──────────────────┘
└───────────────┬────────────────┘
▼
self.all_tools = builtin + plugins
│
┌────────────────────────────────┼─────────────────────────────────┐
│ Support modules │
│ gradients.py Themes/gradients browsers.py Browser picking │
│ config.py ~/.wavetools/config clipboard.py Clipboard │
│ plugin_api.py stable plugin API ascii_art.py Banners/glyphs │
│ faker_render.py Faker images (PIL) │
└──────────────────────────────────────────────────────────────────┘
Core idea: the UI knows nothing about individual tools. A tool is a Tool data object with a run/job function. ToolScreen asks the declared questions, calls run/job, and renders the returned ToolResult. That's why a hand-written plugin looks and behaves exactly like a built-in tool.
File Layout
wavetools/
├── run.py # entry point: python run.py
├── requirements.txt
├── README.md (this file)
└── wavetools/ # the actual package
├── __main__.py # python -m wavetools
├── core/ # app engine + shared non-tool modules
│ ├── app.py # Textual app + screens (UI)
│ ├── builtin_tools.py # Tool/Step/ToolResult/JobContext + built-in tools
│ ├── plugins.py # plugin loader (discover_all) for ../tools
│ ├── plugin_api.py # stable helper API for plugins (http_get, save_file, …)
│ ├── config.py # persistent config (~/.wavetools/config.json)
│ ├── gradients.py # color gradients / themes
│ ├── browsers.py # browser detection & selection
│ ├── clipboard.py # clipboard (pyperclip)
│ ├── ascii_art.py # logo / wave glyphs
│ ├── i18n.py # UI translations (en/de/es/ru)
│ ├── input_folder.py # reusable input folders
│ ├── text_clean.py # text cleanup
│ ├── tutorial.py # onboarding tutorial
│ └── faker_render.py # Faker tools (PIL image output)
├── input/ # saved inputs per category
├── output/ # default output folder for generated files
├── utils/ # shared helpers (logging, networking)
└── tools/ # >>> every plugin lives here <<<
├── osint_dns.py # native Python tool (TOOL + run())
├── net_port_scanner.py # …
├── crack_hash_cracker.py # …
└── …
Everything under wavetools/tools/ is scanned at startup. Files whose name starts with _ or . are skipped (which is why the manifest generator is named _generate_embedded_manifests.py — a build helper, not a tool).
Tool Lifecycle
ToolScreen (app.py) runs through three phases:
ask ──► run ──► result
│ │ │
│ │ └─ render ToolResult (text/list/table/file),
│ │ "run again" console, Ctrl+C to copy
│ └─ run(opts) or job(ctx, opts) on a background thread;
│ streaming tools write live lines via ctx.line()/ctx.status()
└─ ask the declared Step()s in order, validate,
collect into an `answers` dict → reaches run/job as `opts`
Where Tools Come From
WaveToolsApp.__init__ (in app.py) builds the full tool list:
builtin = builtin_tools() # hardcoded built-in tools
community_dir = config.resolve_community_tools_dir(cfg)
plugins, reports = discover_all(BUILTIN_TOOLS_DIR, community_dir)
self.all_tools = builtin + plugins
There are three tool origins (Tool.origin):
origin |
Source | Note |
|---|---|---|
built-in |
builtin_tools() in builtin_tools.py |
hardcoded in code |
bundled |
wavetools/tools/ |
shipped plugins |
community |
optional extra folder (WAVETOOLS_TOOLS_DIR / config) |
flagged as "third-party, unverified" |
For 99% of cases, the recommended path is a .py plugin in wavetools/tools/ — see below.
Three dataclasses (in builtin_tools.py) are the entire vocabulary:
Tool— describes a tool: name, categories, description, therun/jobfunction, theSteps to ask, and metadata.Step— one question in the guided flow (kind,prompt,default, validation, condition, …).ToolResult— the outcome of a run (ok,summary,log, optionaltable/items/path/copy).
Streaming adds JobContext — see the reference below.
Writing a Plugin
Adding a New Category
Categories are not hardcoded. The left-hand column of the main menu is derived at runtime from the tools (MainScreen._build_categories in app.py): any category named by any tool shows up automatically.
TOOL = {
"name": "My New Tool",
"category": "FORENSICS", # <-- doesn't exist yet? -> created automatically
# ...
}
A tool can appear in multiple categories at once via categories (a list). category stays the primary category (shown in the tool view's header):
TOOL = {
"name": "IP Localise",
"category": "OSINT", # primary category
"categories": ["OSINT", "NETWORK"], # appears under BOTH
# ...
}
Order within a category is controlled via order (lower = higher up; equal values keep load order):
TOOL = { "name": "...", "category": "NETWORK", "order": -10 }
There's no central category list to maintain. To retire a category, just remove it from every tool that references it.
Python Plugin (.py)
The recommended way to add a tool to an existing category is a native Python plugin: a file in wavetools/tools/ that defines a TOOL dict and a run function.
Complete minimal example — wavetools/tools/reverse_text.py:
"""Reverses text — minimal example of a WaveTools plugin."""
TOOL = {
"name": "Reverse Text",
"category": "TEXT", # existing category
"description": "Reverses the string. Pure offline tool.",
"api_version": 1, # which plugin API this was written against
"author": "you",
"version": "1.0.0",
"capabilities": [], # uses neither network nor filesystem
"supported_os": ["Windows", "Linux", "Darwin"],
"steps": [
{
"key": "text", # ends up as opts["text"]
"prompt": "Text to reverse",
"kind": "text",
"default": "",
},
],
}
def run(opts):
text = str(opts.get("text", ""))
reversed_text = text[::-1]
return {
"ok": True,
"summary": f"Reversed {len(text)} characters",
"log": [reversed_text],
"copy": reversed_text, # what Ctrl+C copies
}
Save the file, restart WaveTools — done. The tool shows up under TEXT.
Two execution styles:
| Signature | Behavior |
|---|---|
run(opts) |
atomic: runs to completion, returns a result. For fast tools. |
run(opts, ctx) |
streaming: receives a JobContext, can emit live lines and is cancellable. For slow/long-running tools. |
The loader detects which one you wrote from its parameter count. Streaming example:
def run(opts, ctx):
ctx.status("Working …")
for i in range(100):
if ctx.cancelled: # user pressed Esc
return {"ok": False, "summary": "Cancelled."}
ctx.line(f"Step {i}", style="muted")
return {"ok": True, "summary": "Done."}
Return value: a
dict(as above), an(ok, summary, log)tuple, or a plain string are all accepted — the loader coerces them into aToolResult(_coerce_result). Important: the keys areok/summary/log— notsuccess/message. A dict usingsuccess/messagestill loads, but those fields are silently ignored (the tool just shows "Done.").
External Command Plugin (.json)
If your tool isn't Python (a shell script, an .exe, a Node script, …), describe it with a JSON manifest instead. No Python required.
wavetools/tools/my_ping.json:
{
"name": "Quick Ping",
"category": "NETWORK",
"description": "Pings a host using the system ping.",
"api_version": 1,
"author": "you",
"version": "1.0.0",
"capabilities": ["network", "exec"],
"supported_os": ["Windows", "Linux", "Darwin"],
"steps": [
{ "key": "host", "prompt": "Host", "kind": "text", "default": "8.8.8.8" }
],
"command": {
"Windows": ["ping", "-n", "4", "{host}"],
"Linux": ["ping", "-c", "4", "{host}"],
"Darwin": ["ping", "-c", "4", "{host}"]
},
"timeout": 30
}
How execution works (_make_external_runner in plugins.py):
commandis either an OS map (Windows/Linux/Darwin/default) or a single value.{key}placeholders in the command list are substituted with collected answers (str.format(**opts)). In the example,{host}becomes the input.timeout(seconds) bounds the run;0ornull= no limit.- stdout/stderr are captured and shown as the result log; exit code
0counts as success.
Watch out for interactive scripts: external commands run without a TTY/stdin. Scripts that call
input(), draw a menu, or clear the screen won't work sensibly this way. For those, a native Python port (above) is the right fix.
Plugin API Reference
The TOOL Manifest
All fields (apply equally to .py TOOL dicts and .json manifests unless noted):
| Field | Type | Required | Meaning |
|---|---|---|---|
name |
str | Display name + banner | |
category |
str | primary category | |
description |
str | recommended | text shown above the questions |
categories |
list[str] | – | extra categories (multi-listing) |
steps |
list[dict] | – | the steps to ask (below) |
settings |
list[dict] | – | legacy alternative to steps (auto-converted) |
supported_os |
list[str] | – | Windows/Linux/Darwin; default: all |
api_version |
int | recommended | plugin API version this was written against |
author |
str | – | shown in the transparency panel |
version |
str | – | plugin version |
requires |
list[str] | – | required Python imports/packages (dependency check) |
capabilities |
list[str] | – | declared capabilities: network/filesystem/exec |
order |
int | – | sort hint within the category |
prompt / prompt_key |
str | – | legacy single-question shorthand |
command |
dict/list/str | .json only |
the command to run |
timeout |
int | .json only |
limit in seconds (0/null = no limit) |
.py plugins may additionally define these module functions: run (required), steps_for(answers), setup(), teardown().
Step Kinds
Every entry in steps is a dict. Common keys: key (answer key in opts), prompt (question, alias: label), kind, default (alias: value).
kind |
Input | Answer type |
|---|---|---|
text |
free text (paste allowed) | str |
password |
masked free text (•) |
str |
number |
number, respects min/max/integer |
str (numeric) |
bool |
on/off toggle | bool |
choice |
one option from choices |
str |
multiselect |
multiple from choices (space toggles) |
list[str] |
file |
local file path (existence checked) | str |
date |
date YYYY-MM-DD (validated) |
str |
"steps": [
{"key": "domain", "prompt": "Domain", "kind": "text", "default": "example.com"},
{"key": "port", "prompt": "Port", "kind": "number", "min": 1, "max": 65535, "integer": True},
{"key": "deep", "prompt": "Deep scan?", "kind": "bool", "default": False},
{"key": "proto", "prompt": "Protocol", "kind": "choice", "choices": ["http", "https"]},
{"key": "types", "prompt": "Record types", "kind": "multiselect",
"choices": ["A", "AAAA", "MX"], "default": ["A"]},
]
Validation & Conditions
Declarative per-step validation (works in .py and .json) via validate:
{"key": "url", "prompt": "URL", "kind": "text",
"validate": {"required": True, "url": True, "message": "Please enter an http(s) URL"}}
Supported validation keys (_compile_validate in plugins.py): required, min_len, max_len, integer, url, email, regex (+ flags: "i"), message. In .py plugins you can instead supply a function validate(value, answers) -> str|None (error text or None).
number/date/file steps have additional built-in checks (numeric bounds, date format, file exists).
A step can be shown only under a condition (when, alias condition). If the condition isn't met, the step is skipped and its default is stored:
{"key": "platform", "prompt": "Platform", "kind": "choice", "choices": ["TikTok", "X"]},
{"key": "handle", "prompt": "TikTok handle", "kind": "text",
"when": {"key": "platform", "equals": "TikTok"}}
Supported condition keys (_compile_condition): equals, is, not, in (list), truthy, falsy. In .py, a function condition(answers) -> bool is also allowed.
The ToolResult Format
run/job return a dict (or a ToolResult). Fields:
| Key | Type | Effect |
|---|---|---|
ok |
bool | success/failure (green / red ). Default True |
summary |
str | result header line |
log |
list[str] | text lines (default rendering) |
table + headers |
list[list[str]] + list[str] | render as an aligned table |
items |
list[str] | render as a bulleted list |
path |
str | "Saved: …"; Ctrl+O opens the file |
copy |
str | what Ctrl+C copies (otherwise: log/summary) |
kind |
str | force render mode: text/list/table/file/auto |
return {
"ok": True,
"summary": "3 records found",
"headers": ["Type", "Value"],
"table": [["A", "93.184.216.34"], ["MX", "mail.example.com"]],
"copy": "A 93.184.216.34\nMX mail.example.com",
}
The JobContext (Streaming Tools)
A job/run(opts, ctx) receives ctx and uses it to drive the live window. All callbacks are thread-safe (the job runs on a background thread):
| Call | Effect |
|---|---|
ctx.line(text, style=None) |
emit one line; style: ok/bad/warn/muted/header/None |
ctx.status(text) |
update the header status line |
ctx.cancelled |
True once the user cancels (check it in loops!) |
ctx.set_copy(text) |
set what Ctrl+C copies |
ctx.open_url(url) |
open a URL in the selected browser |
ctx.browser |
the browser chosen in settings |
ctx.ascii_only |
True when ASCII mode is active (no fancy glyphs) |
ctx.store |
persistent plugin storage (below) |
The plugin_api helpers are also available directly on ctx: ctx.save_file(...), ctx.http_get(...), ctx.copy(...), ctx.open_path(...), ctx.get_config().
plugin_api Helpers
Importable from any plugin (even from an atomic run(opts)):
from wavetools.core.plugin_api import http_get, save_file, copy_text, get_store, open_url, open_path, get_config
| Function | Description |
|---|---|
http_get(url, *, timeout=15, headers=None) |
GET; returns {ok, status, text, error} — never raises |
save_file(name, data, *, binary=False) |
write into the output folder; returns the path (name is reduced to its basename — no writing outside it) |
copy_text(text) |
copy to clipboard (best effort) |
open_url(url, browser=None) |
open in the configured browser |
open_path(path) |
open a file with the configured editor / OS default |
get_store(plugin_id) |
get persistent storage (below) |
get_config() |
reads {output_dir, browser, ascii_only} |
Everything is fail-soft: a helper never raises, it reports success/failure in its return value instead.
Persistent Plugin Storage (PluginStore)
An isolated key/value store per plugin, saved under ~/.wavetools/plugin_data/<id>.json. One plugin can neither read nor overwrite another's data.
ctx.store.set("last_target", target)
last = ctx.store.get("last_target", "")
ctx.store.all() # everything as a dict
ctx.store.delete("k") # delete one key
ctx.store.clear() # delete everything
Lifecycle hooks — optional module functions in a .py plugin:
def setup():
"""Runs once when the tool is opened."""
def teardown():
"""Runs when the tool is left."""
Errors in hooks are fail-soft (noted in diagnostics, never crash the app).
Repeatable question groups — if a .py plugin defines steps_for(answers), the step list is recomputed from it after every answer. This lets questions grow dynamically ("Message #N" + "one more?") as long as the user keeps saying yes. The already-answered prefix must stay stable — only the tail may grow/shrink.
def steps_for(answers):
steps = [{"key": "msg1", "prompt": "Message #1", "kind": "text"}]
n = 1
while answers.get(f"more{n}") is True:
n += 1
steps.append({"key": f"msg{n}", "prompt": f"Message #{n}", "kind": "text"})
steps.append({"key": f"more{n}", "prompt": "One more?", "kind": "bool"})
return steps
Versioning & Compatibility
PLUGIN_API_VERSION(inbuiltin_tools.py) is the current API version.- A plugin declares, via
api_version, which version it was written against. The loader decides from that (_version_decision):- newer than the app → skipped (app is too old),
- older than
MIN_SUPPORTED_API_VERSION→ skipped, - no
api_version→ compatibility mode ("legacy"), still loads, - older but still supported → compatibility mode.
- If a library named in
requiresis missing, the tool still loads (visibly), but explains what topip installat startup (_deps_guard).
Every load produces a PluginReport (status loaded/compat/needs-deps/skipped), viewable in the app's diagnostics window.
Capabilities & security model: capabilities is a self-declaration (network/filesystem/exec) shown transparently in the tool description — it is not an enforced sandbox. Plugins (origin bundled/community) require a one-time confirmation before their first run (remembered in config); community tools are additionally flagged as "third-party, unverified". A plugin runs with the user's own privileges. Only install/enable tools whose source you understand.
Configuration
Configuration lives in ~/.wavetools/config.json (creatable/editable via the settings menu, key S on the main menu). Environment variables take precedence:
| Variable | Effect |
|---|---|
WAVETOOLS_CONFIG |
path to the config file (portable operation) |
WAVETOOLS_TOOLS_DIR |
extra community plugin folder |
WAVETOOLS_OUTPUT_DIR |
destination folder for generated files |
WAVETOOLS_INPUT_DIR |
folder for reusable inputs (tokens, webhooks, …) |
Stored values include: language, gradient (theme), browser, input_dir, output_dir, community_tools_dir, ascii_only, editor, configured (first-run done), accepted plugins, and optional per-tool default answers. A missing/broken config silently falls back to safe defaults.
First-run wizard & languages: on the very first launch (configured = false), a one-time setup wizard appears: language, theme, browser, ASCII mode, input/output/community folders, and editor. Everything can be changed later under Settings (S). Available UI languages: English (default), German, Spanish, Russian. Only the program's own UI (menus, status lines, settings, wizard) is translated — text produced by tools stays in its original language.
Input folder (reusable inputs): instead of pasting the same cookie / proxy / wordlist on every run, drop it once into the input folder (wavetools/input, created automatically with subfolders + a README on first launch):
| Subfolder | Contents (one entry per line, # = comment) |
|---|---|
roblox_cookies/ |
.ROBLOSECURITY cookies |
proxies/ |
ip:port or user:pass@ip:port |
wordlists/ |
any list (passwords, names, paths, …) |
When a tool asks for one of these values, WaveTools shows "Use from Input-Folder (N)" automatically — Ctrl+F fills the field straight from the folder (cycle through single values, or insert everything for lists). .txt files are validated and deduplicated.
Tool Catalog
66 bundled tools (plus built-in System/Text utilities). = use only where you are authorized; may carry Terms-of-Service or legal weight depending on the target.
MINECRAFT (1 tool)
| Tool | Description | Disclaimer |
|---|---|---|
mc_name_sniper |
Snipe an expiring Minecraft name onto your own account (Microsoft device-code login, NTP-timed change requests) |
NETWORK (16 tools)
| Tool | Description | Disclaimer |
|---|---|---|
dns_lookup |
DNS query (A, AAAA, MX, TXT, NS, CNAME, SOA) via DNS-over-HTTPS | — |
ip_localisation |
Geolocate an IP: country, city, ISP, ASN, VPN/proxy/hosting flags, maps link | — |
net_domain_intel |
Domain A-record + HTTP header report (security headers) | — |
net_ip_all_lookup |
Parallel deep-dive: GeoIP + VPN + SSL + port scans | |
net_ip_blacklist_checker |
Check an IP against 5 DNSBLs (Spamhaus, Barracuda, SORBS, SpamCop) | — |
net_ip_deep_scan |
Comprehensive IP scan: type, ping, rDNS, ports, GeoIP, SSL | |
net_ip_generator |
Generate random IPs and test reachability | — |
net_port_scanner |
TCP port scan for a host (single or range) | |
net_proxy_checker |
Validate a proxy list and check anonymity | — |
net_proxy_scraper |
Scrape free proxy lists from public sources | — |
net_ssl_checker |
Show SSL/TLS certificate details and expiry | — |
net_tcp_pinger |
TCP ping: measure connect latency to host:port | — |
network_ip_pinger |
ICMP ping multiple hosts at once (avg/min/max) | — |
system_info |
Show OS, CPU, RAM, disk, GPU, network interfaces | — |
OSINT (19 tools)
| Tool | Description | Disclaimer |
|---|---|---|
osint_database_search |
Local file and database search (UTF-8/Latin-1) | — |
osint_email_info |
Fetch a domain's MX, SPF, and DMARC records | — |
osint_email_osint |
Check email registration across 8 platforms (Instagram, GitHub, Twitter/X, Spotify, Duolingo, …) | — |
osint_exif |
Extract EXIF metadata from image files | — |
osint_github_lookup |
GitHub profile: bio, followers, top repos, orgs | — |
osint_google_dork |
Generate pre-built Google dork queries | — |
osint_instagram_lookup |
Fetch Instagram profile information | — |
osint_ip_reputation |
IP reputation check with a heuristic risk score | — |
osint_ip_vpn_detector |
VPN/proxy/datacenter detection for an IP | — |
osint_mac_lookup |
MAC address → vendor lookup (OUI) | — |
osint_name_tracker |
Search a username across 18 platforms at once | — |
osint_phone_lookup |
Geolocate a phone number and fetch carrier info | — |
osint_social_platforms |
Look up Kick.com, Minecraft, Telegram, TikTok, Snapchat | — |
osint_subdomain_finder |
Find subdomains of a domain via DNS enumeration | — |
osint_username_hunter |
Look up a username across dozens of platforms | — |
osint_youtube_lookup |
Look up a YouTube channel (@handle) or video (ID/URL) | — |
email_breach_finder |
Search an email address in known data breaches (HIBP) | — |
ROBLOX (13 tools)
| Tool | Description | Disclaimer |
|---|---|---|
roblox_account_info |
Look up a user by username or ID (profile, presence, followers, groups, avatar) | — |
roblox_avatar |
Avatar assets and headshot thumbnails (single or batch) | — |
roblox_badges |
Earned badges + collectibles/limiteds inventory (cookie required) | — |
roblox_cookie_info |
Account details via a .ROBLOSECURITY cookie (Robux, email, groups, PIN) |
— |
roblox_game_extras |
Game votes, gamepass info, place → universe converter | — |
roblox_game_info |
Game stats, active players, ratings | — |
roblox_group_extras |
Group roles with member counts, group Robux balance | — |
roblox_group_info |
Group details, member count, owner | — |
roblox_id_info |
Query a user ID directly (no username resolution) | — |
roblox_items |
Item details, limited/resale price (RAP), catalog search | — |
roblox_multi |
Bulk cookie validation + profile JSON export | — |
roblox_social |
Friends list, follower/following count, account age | — |
roblox_username_checker |
Check Roblox username availability | — |
WEBSITE (7 tools)
| Tool | Description | Disclaimer |
|---|---|---|
web_admin_finder |
Probe ~40 common admin/login/control-panel paths | |
web_dir_finder |
Probe ~60 common directories and files (backups, .env, .git/, …) |
|
web_full_scanner |
Recon: resolve IP, open ports, headers, SSL, tech detection | |
web_info_scanner |
One passive GET: status, server/x-powered-by headers, page info | — |
web_security_headers |
Grade a URL's HTTP security response headers | — |
web_url_scanner |
URL safety heuristics: scheme, redirect chain, suspicious patterns | — |
web_vuln_scanner |
Low-impact checks: weak security headers, exposed sensitive files |
GENERATOR (4 tools)
| Tool | Description | Disclaimer |
|---|---|---|
password_generator |
Secure random passwords with configurable rules | — |
qr_code_generator |
Generate a QR code as a PNG file | — |
temporary_mail |
Disposable email address via the mail.tm API | — |
text_encoder_decoder |
Encode/decode Base64, URL, HTML, hex, binary, ROT13 | — |
CRYPTO (6 tools)
| Tool | Description | Disclaimer |
|---|---|---|
crack_hash_cracker |
Offline dictionary attack on a hash (MD5, SHA1, SHA256, SHA512, bcrypt) | |
crack_hash_identifier |
Detect hash format from length/prefix | — |
crack_jwt_decoder |
Decode a JWT, show algorithm and claims (no signature check) | — |
crack_password_hasher |
Hash text with various algorithms + optional salt | — |
crack_zip_cracker |
Offline dictionary attack on a password-protected ZIP | |
file_hasher |
Compute MD5/SHA1/SHA256/SHA512 hash of a file | — |
Tools whose filename starts with _ or . are skipped by the plugin loader (build helpers, not tools).
Security & Legal Notice
WaveTools includes network, OSINT and website-recon tooling. Use it exclusively against systems, accounts, and networks you have explicit permission to test — your own infrastructure, authorized penetration tests, CTFs, and education. Scanning, enumeration, dictionary cracking and automated account actions can carry Terms-of-Service or legal weight depending on how and where you use them — that responsibility is yours. Tools flagged in the Tool Catalog are the ones to be especially careful with (they actively probe a target, run dictionary attacks, or automate account changes such as the Minecraft name snipe, which is against Mojang's ToS and should only ever target your own account).
Plugins run with your own privileges and without a sandbox. Only load tools from sources you understand and trust, and consciously confirm a plugin before its first run.
Roadmap
- [x] Runtime plugin loader (
.py+.json) - [x] Reusable input folder with
Ctrl+Fautofill - [x] Multi-language UI (en/de/es/ru)
- [x] Plugin API versioning & compatibility mode
- [ ] Automated test suite / CI
- [ ] Plugin marketplace / community index
- [ ] Additional language packs
Track proposed features and known issues in your repository's issue tracker.
Contributing
Contributions make the open-source community an amazing place to learn, get inspired, and build. Any contribution you make is greatly appreciated.
If you have a suggestion, fork the repo and open a pull request, or simply open an issue tagged "enhancement". Don't forget to star the project — thanks again!
- Fork the project
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a pull request
New tool plugins are the easiest way to contribute — see Writing a Plugin above; a single well-formed .py file in wavetools/tools/ is a complete contribution.
License
Distributed under the MIT License. See LICENSE for the full text.
Contact
WaveTools — a blue, wave-themed multi-tool TUI, by AquA.
For bugs and feature requests, use the issue tracker of the repository you cloned this from.
Acknowledgments
- Textual and Rich — the TUI engine this project is built on
- Best-README-Template — structure and inspiration for this README
- Img Shields — the badges up top
- Choose an Open Source License