wave4real/WaveTools

GitHub: wave4real/WaveTools

一款基于 Textual 的动画终端多工具箱,通过运行时插件系统将安全、OSINT、网络及各类实用工具整合为统一的引导式 TUI 体验。

Stars: 1 | Forks: 0


####
██ ██ ▄▄▄ ▄▄ ▄▄ ▄▄▄▄▄ ██████ ▄▄▄ ▄▄▄ ▄▄ ▄▄▄▄ ██ ▄█▄ ██ ██▀██ ██▄██ ██▄▄ ██ ██▀██ ██▀██ ██ ███▄▄ #### ▀██▀██▀ ██▀██ ▀█▀ ██▄▄▄ ██ ▀███▀ ▀███▀ ██▄▄▄ ▄▄██▀

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
  1. About The Project
  2. Built With
  3. Getting Started
  4. Usage
  5. Plugin Architecture
  6. Writing a Plugin
  7. Plugin API Reference
  8. Configuration
  9. Tool Catalog
  10. Security & Legal Notice
  11. Roadmap
  12. Contributing
  13. License
  14. Contact
  15. 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](https://img.shields.io/badge/Python-3776AB?style=for-the-badge&logo=python&logoColor=white)][Python-url] * [![Textual](https://img.shields.io/badge/Textual-5967FF?style=for-the-badge&logo=python&logoColor=white)][Textual-url] * [![Rich](https://img.shields.io/badge/Rich-FF4785?style=for-the-badge&logo=python&logoColor=white)][Rich-url] * [![discord.py](https://img.shields.io/badge/discord.py-5865F2?style=for-the-badge&logo=discord&logoColor=white)][Discordpy-url] * [![aiohttp](https://img.shields.io/badge/aiohttp-2C5BB4?style=for-the-badge&logo=python&logoColor=white)][Aiohttp-url] * [![Cryptography](https://img.shields.io/badge/cryptography-000000?style=for-the-badge&logo=letsencrypt&logoColor=white)][Cryptography-url] * [![Pillow](https://img.shields.io/badge/Pillow-4B8BBE?style=for-the-badge&logo=python&logoColor=white)][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/
标签:ESC4, GitHub, OSINT, Web工具, 加密货币工具, 多功能工具箱, 实时处理, 游戏工具, 跨平台, 逆向工具