####
██ ██ ▄▄▄ ▄▄ ▄▄ ▄▄▄▄▄ ██████ ▄▄▄ ▄▄▄ ▄▄ ▄▄▄▄
██ ▄█▄ ██ ██▀██ ██▄██ ██▄▄ ██ ██▀██ ██▀██ ██ ███▄▄
#### ▀██▀██▀ ██▀██ ▀█▀ ██▄▄▄ ██ ▀███▀ ▀███▀ ██▄▄▄ ▄▄██▀
WaveTools
An animated terminal UI (TUI) toolbox for security, OSINT, network and utility tools — with a live-reloading plugin system at its core.
Explore the architecture »
Browse the Tool Catalog
·
Report Bug
·
Request Feature
Table of Contents
- About The Project
- Built With
-
Getting Started
-
Usage
-
Plugin Architecture
-
Writing a Plugin
-
Plugin API Reference
- Configuration
- Tool Catalog
- Security & Legal Notice
- Roadmap
- Contributing
- License
- Contact
- Acknowledgments
##
## About The Project
WaveTools is an animated terminal UI (TUI), built on [Textual](https://textual.textualize.io/), 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.
* 🌍 **~121 tools across 7 categories** — Discord, Network, OSINT, Roblox, Website, Generator, Crypto.
* 🔌 **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+F` instead 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.
(back to top)
### Built With
* [][Python-url]
* [][Textual-url]
* [][Rich-url]
* [][Discordpy-url]
* [][Aiohttp-url]
* [][Cryptography-url]
* [][Pillow-url]
##
(back to top)
## Getting Started
### Prerequisites
* **Python 3.10+** (CPython). All core dependencies are pinned in `requirements.txt`.
* On Windows, `install.bat` / `start.bat` handle the Python launcher detection for you.
### Installation
1. Clone the repo
git clone https://github.com/wave4real/WaveTools.git
cd WaveTools
2. Install dependencies
pip install -r requirements.txt
On Windows you can instead double-click / run `install.bat`, which finds a Python launcher, upgrades `pip`, and installs everything for you.
3. Launch WaveTools
python run.py
On Windows, `start.bat` does the same with launcher auto-detection.
##
(back to top)
## 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) |
##
(back to top)
## 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, the `run`/`job` function, the `Step`s 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`, optional `table`/`items`/`path`/`copy`).
Streaming adds **`JobContext`** — see the reference below.
##
(back to top)
## 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.
```python
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):
```python
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):
```python
#### 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`:
```python
"""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:
```python
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 a `ToolResult` (`_coerce_result`). **Important:** the keys are `ok`/`summary`/`log` — **not** `success`/`message`. A dict using `success`/`message` still 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`:
```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`):
* `command` is 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; **`0` or `null` = no limit**.
* stdout/stderr are captured and shown as the result log; exit code `0` counts 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.
##
(back to top)
## 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` |
```python
"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`:
```python
{"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:
```python
{"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` |
```python
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)`):
```python
#### 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/
.json`. One plugin can neither read nor overwrite another's data.
```python
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:
```python
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.
```python
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` (in `builtin_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 `requires` is missing, the tool still loads (visibly), but explains what to `pip install` at 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.**
## (back to top)
## 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 Discord token / webhook / proxy 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) |
|-----------|-----------------------------------------------|
| `discord_tokens/` | Discord user/bot tokens |
| `discord_webhooks/` | Discord webhook URLs |
| `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.
## (back to top)
## Tool Catalog
> **~121 tools across 7 categories.** Disclaimer levels: ⚠ ToS risk · ⚠⚠ destructive/ban risk · ⚠⚠⚠ irreversible/legal risk.
DISCORD (50 tools)
| Tool | Description | Disclaimer |
|------|-------------|------------|
| `discord_bot_invite_generator` | Build a bot invite URL from a bot ID | — |
| `discord_bot_nuker` | Bot-driven server nuker (all channels, roles, bans) | ⚠⚠⚠ |
| `discord_bot_raider` | Bot for mass channel/role creation | ⚠⚠⚠ |
| `discord_embed_creator` | Build a rich embed block for webhooks | — |
| `discord_guild_leaver` | Leave or delete all guilds of a token | ⚠⚠ |
| `discord_injection_cleaner` | Scan local Discord files for token-stealer injections | — |
| `discord_multi_token_joiner` | Have multiple tokens join a server | ⚠⚠ |
| `discord_selfbot` | Nitro sniper + automatic status rotator | ⚠⚠ |
| `discord_server_ban_all` | Ban every member of a server | ⚠⚠⚠ |
| `discord_server_cloner` | Clone a server's channel/role structure | ⚠⚠ |
| `discord_server_compare` | Compare two servers via invite code | — |
| `discord_server_editor` | Change server name, icon, region, verification level | ⚠⚠ |
| `discord_server_info` | Fetch public server info via invite code | — |
| `discord_server_kick_all` | Kick every member of a server | ⚠⚠⚠ |
| `discord_server_mute_all` | Mute every member | ⚠⚠ |
| `discord_server_scraper` | Export a server's member list and channels | ⚠⚠ |
| `discord_server_unban_all` | Lift all active bans | ⚠⚠ |
| `discord_token_bio_changer` | Change a token's bio/"About Me" | ⚠ |
| `discord_token_block_friends` | Block all of a token's friends | ⚠ |
| `discord_token_bruteforce` | Token brute-force via user ID or bulk file check | ⚠⚠⚠ |
| `discord_token_delete_dms` | Close all DM channels of a token | ⚠ |
| `discord_token_delete_friends` | Remove all of a token's friends | ⚠ |
| `discord_token_disabler` | Permanently disable a token's account | ⚠⚠⚠ |
| `discord_token_generator` | Register Discord accounts via temp mail + captcha API | ⚠⚠⚠ |
| `discord_token_ghost_pinger` | Send a ghost ping (message deleted instantly) | ⚠ |
| `discord_token_house_changer` | Change HypeSquad house (Bravery/Brilliance/Balance) | — |
| `discord_token_image_changer` | Change a token's avatar or banner | ⚠ |
| `discord_token_info` | Fetch token information and account details | — |
| `discord_token_joiner` | Have a token join a server via invite | ⚠⚠ |
| `discord_token_language_changer` | Set a token's app language | ⚠ |
| `discord_token_leaver` | Have a token leave one or all servers | ⚠ |
| `discord_token_login` | Check token validity, show account info | — |
| `discord_token_mass_dm` | Message all friends/guilds via DM | ⚠⚠⚠ |
| `discord_token_mass_pfp` | Set an avatar for multiple tokens at once | ⚠⚠ |
| `discord_token_nuker` | Delete all channels and roles of your own server | ⚠⚠⚠ |
| `discord_token_onliner` | Keep an online presence via WebSocket heartbeat | ⚠⚠ |
| `discord_token_server_raid` | Spam multiple tokens + channels simultaneously | ⚠⚠⚠ |
| `discord_token_spammer` | Channel spam with configurable delay and repeat count | ⚠⚠⚠ |
| `discord_token_status_changer` | Set a token's custom status | — |
| `discord_token_theme_changer` | Set or toggle dark/light theme | — |
| `discord_token_to_id` | Decode token → user ID; ID → token prefix; brute-force | ⚠⚠ |
| `discord_user_lookup` | Decode a snowflake ID + optional profile via bot token | — |
| `discord_vanity_sniper` | Watch and snipe vanity URL changes | ⚠⚠ |
| `discord_vc_joiner` | Have tokens join a voice channel via gateway WebSocket | ⚠⚠ |
| `discord_webhook_deleter` | Permanently delete a webhook | ⚠⚠ |
| `discord_webhook_info` | Fetch webhook details (platform detection, security info) | — |
| `discord_webhook_manager` | Edit, clone, or create webhooks | ⚠⚠ |
| `discord_webhook_scanner` | Webhook brute-force scanner (ID range) | ⚠⚠ |
| `discord_webhook_sender` | Send a webhook message in 7 modes (TTS, silent, ghost, …) | ⚠ |
| `discord_webhook_spammer` | Webhook spam with delay and count | ⚠⚠⚠ |
NETWORK (17 tools)
| Tool | Description | Disclaimer |
|------|-------------|------------|
| `dark_web_links` | Categorized .onion link list, for reference | — |
| `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 | — |
| `web_full_scanner` | Full website scan (headers, SSL, ports, cookies, tech detection) | — |
OSINT (~20 tools)
| Tool | Description | Disclaimer |
|------|-------------|------------|
| `osint_database_search` | Local file and database search (UTF-8/Latin-1) | — |
| `osint_dox_creator` | Build a personal dossier from collected OSINT data | — |
| `osint_dox_tracker` | Generate social-media search URLs for a person | — |
| `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 (8 tools)
| Tool | Description | Disclaimer |
|------|-------------|------------|
| `web_admin_finder` | Find admin panel paths on a website via wordlist | — |
| `web_basic_auth_bf` | HTTP Basic Auth brute-forcer (default + custom wordlist) | ⚠⚠ |
| `web_cloner` | Save a website's HTML and assets locally | — |
| `web_dir_finder` | Discover directories and files via wordlist | — |
| `web_full_scanner` | Full scan: headers, SSL, ports, cookies, tech detection, security headers | — |
| `web_security_headers` | Check and rate a URL's HTTP security headers | — |
| `web_url_scanner` | Check a URL against known blacklists and reputation | — |
| `web_vuln_scanner` | Basic web vulnerability detection (XSS, SQLi, IDOR) | — |
GENERATOR (7 tools)
| Tool | Description | Disclaimer |
|------|-------------|------------|
| `gen_gift_code_generator` | Generate random gift-code strings in platform formats (Amazon, Netflix, Steam, …) | ⚠ |
| `nitro_code_generator` | Generate random Discord Nitro code strings | — |
| `password_generator` | Secure random passwords with configurable rules | — |
| `python_obfuscator` | Obfuscate Python source code (Base64 encoding) | — |
| `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` | Crack hash values via wordlist (MD5, SHA1, SHA256, SHA512, bcrypt) | — |
| `crack_hash_identifier` | Detect hash format from length/prefix | — |
| `crack_jwt_decoder` | Decode a JWT, show algorithm and claims | — |
| `crack_password_hasher` | Hash text with various algorithms | — |
| `crack_zip_cracker` | Crack password-protected ZIP files via wordlist | — |
| `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).*
## (back to top)
## 🔒 Security & Legal Notice
WaveTools bundles security tooling. Use it **exclusively** against systems, accounts, and networks you have **explicit permission** to test — your own infrastructure, authorized penetration tests, CTFs, education. OSINT/network/crack tools can carry legal weight depending on how you use them — that responsibility is yours.
Plugins run with your own privileges and without a sandbox. Only load tools from sources you understand and trust; consciously confirm a plugin before its first run. Tools flagged ⚠⚠ or ⚠⚠⚠ in the [Tool Catalog](#-tool-catalog) are destructive and/or effectively irreversible (mass bans/kicks, server nuking, account disabling, mass DMs). Misusing them against services or accounts you don't own or aren't contracted to test can violate a platform's Terms of Service and/or the law.
## (back to top)
## Roadmap
- [x] Runtime plugin loader (`.py` + `.json`)
- [x] Reusable input folder with `Ctrl+F` autofill
- [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
See the [open issues](https://github.com/wave4real/WaveTools/issues) for the full list of proposed features (and known issues).
## (back to top)
## 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!
1. Fork the project
2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
4. Push to the branch (`git push origin feature/AmazingFeature`)
5. Open a pull request
New tool plugins are the easiest way to contribute — see [Writing a Plugin](#writing-a-plugin) above; a single well-formed `.py` file in `wavetools/tools/` is a complete contribution.
## (back to top)
## License
Distributed under the MIT License. See [`LICENSE`](LICENSE) for the full text.
## (back to top)
## Contact
Project Link: [https://github.com/wave4real/WaveTools](https://github.com/wave4real/WaveTools)
Bugs and feature requests: [GitHub Issues](https://github.com/wave4real/WaveTools/issues)
## (back to top)
## Acknowledgments
* [Textual](https://textual.textualize.io/) and [Rich](https://rich.readthedocs.io/) — the TUI engine this project is built on
* [Best-README-Template](https://github.com/othneildrew/Best-README-Template) — structure and inspiration for this README
* [Img Shields](https://shields.io) — the badges up top
* [Choose an Open Source License](https://choosealicense.com)
(back to top)
[contributors-shield]: https://img.shields.io/github/contributors/wave4real/WaveTools.svg?style=for-the-badge
[contributors-url]: https://github.com/wave4real/WaveTools/graphs/contributors
[forks-shield]: https://img.shields.io/github/forks/wave4real/WaveTools.svg?style=for-the-badge
[forks-url]: https://github.com/wave4real/WaveTools/network/members
[stars-shield]: https://img.shields.io/github/stars/wave4real/WaveTools.svg?style=for-the-badge
[stars-url]: https://github.com/wave4real/WaveTools/stargazers
[issues-shield]: https://img.shields.io/github/issues/wave4real/WaveTools.svg?style=for-the-badge
[issues-url]: https://github.com/wave4real/WaveTools/issues
[license-shield]: https://img.shields.io/github/license/wave4real/WaveTools.svg?style=for-the-badge
[license-url]: https://github.com/wave4real/WaveTools/blob/main/LICENSE
[python-shield]: https://img.shields.io/badge/python-3.10%2B-blue.svg?style=for-the-badge&logo=python&logoColor=white
[python-url]: https://www.python.org/downloads/
[textual-shield]: https://img.shields.io/badge/built%20with-Textual-5967FF.svg?style=for-the-badge
[textual-url]: https://textual.textualize.io/
[platform-shield]: https://img.shields.io/badge/platform-Windows%20%7C%20Linux%20%7C%20macOS-lightgrey.svg?style=for-the-badge
[platform-url]: #getting-started
[Python-url]: https://www.python.org/
[Rich-url]: https://rich.readthedocs.io/
[Discordpy-url]: https://discordpy.readthedocs.io/
[Aiohttp-url]: https://docs.aiohttp.org/
[Cryptography-url]: https://cryptography.io/
[Pillow-url]: https://python-pillow.org/