otinstaller
A beginner guide to installing otinstaller on Linux, running a first tool, and reading the saved output. Free, and not billed to an OSINTverse wallet.
otinstaller installs command line tools by name, runs them, and saves the output. You do not learn a separate install method for each tool.
It downloads other people's software from PyPI or GitHub into a private folder for that tool. otinstaller does not write those tools. You are responsible for how you use them.
This page is the full guide. If you only want the shortest path, follow Before you start and Your first run, then come back for the rest.
Status: early development. Not published to PyPI yet. SearchIn and GraphIn are separate products and use a prepaid wallet. otinstaller does not. It runs on your own machine.
Before you start
You need Linux, Python 3.10 or newer, git, and Python's venv module. A virtualenv is a private Python folder. otinstaller uses one so a tool cannot change the Python that came with the system.
On Debian, Ubuntu and Kali:
sudo apt install python3-venv gitTested distributions are listed under Supported Linux. If yours is not in that table, otinstaller doctor still tells you what failed.
A few words used below:
- A tool is one program from the list, such as
sherlock. You install and run it by that name. - A target is what you ask the tool to look at, such as a username or a domain. Use only targets you are allowed to investigate.
--in a command marks the end of otinstaller's own options. Everything after it is passed to the tool.
Install otinstaller
These commands install otinstaller itself. Run them in the repository folder. They do not install Sherlock or any other tool yet.
python3 -m venv .venvsource .venv/bin/activatepip install -e .Open a new terminal later and run source .venv/bin/activate again if otinstaller is not found. The activation lasts only for that terminal.
When a published package exists, the install will be:
pip install otinstallerCheck the machine before the first tool:
otinstaller doctorEach line is [ok] or [problem]. A [problem] line often names the package to install. Fix those before you continue. doctor checks Linux, Python 3.10 through 3.12, git, venv, and that it can write to its home folder.
Your first run
init creates ~/.otinstaller/ on your machine and prints a responsible-use notice. Read it. Type y and press Enter to accept. Install is refused until you do. The capital N in [y/N] means pressing Enter alone means no.
otinstaller initSherlock searches for a username across social networks. This asks Install? [y/N]. Type y.
otinstaller install sherlockotinstaller run sherlock -- someexampleuser123someexampleuser123 is the target. It is a made-up username for this example. The -- is required so otinstaller does not treat the username as one of its own options.
A finished run looks like this:
tool exited 0
saved to results/sherlock/someexampleuser123/20260922-143000_sherlock_someexampleuser123_a1b2c3d4.txt
sha256 3b1c...tool exited 0 means Sherlock finished without an error. The path is a file in results/, inside the folder where you ran the command. Open that file to read the output. The sha256 line is a fingerprint of the file, so you can tell later if it changed.
Add --verbose on run if you also want the tool's output in the terminal while it is saved.
To run a different tool, find its name in Covered tools and use that name instead of sherlock. Match the input type in the table to what you have. A username tool will not accept a domain.
More ways to run
You can skip this section until the first run works.
Pass a tool its own flags
Flags after -- go to the tool, unchanged. theHarvester looks up a domain, and -d is its own flag for that domain:
otinstaller run theharvester -- -d example.com -b bingRun several tools on the same target
Name every tool before --. They share the same arguments and run together, up to four at a time. --parallel changes that limit.
otinstaller run sherlock maigret -- someexampleuser123otinstaller run sherlock maigret --parallel 2 -- someexampleuser123If the target text is itself a tool name, otinstaller would try to run it as a tool. Pass it with --target so that does not happen:
otinstaller run sherlock --target holehe -- holeheKeep related runs in one case
A case is a folder name you choose, so several runs stay together. --case works on run, auto, extract and diff.
otinstaller run sherlock --case demo-run -- someexampleuser123otinstaller extract sherlock --case demo-runotinstaller diff sherlock someexampleuser123 --case demo-runextract pulls emails, domains, IP addresses and URLs out of saved text files. diff prints lines added and removed between the two newest runs of the same tool and target. You need two finished runs before diff has anything to compare.
Let otinstaller choose the tools
auto guesses whether the target is an email, domain, IP address, URL or username, then runs every installed tool that accepts that kind of target. It does not install missing tools. It lists them and skips them.
--dry-run prints the plan and runs nothing. --type overrides the guess when it is wrong.
otinstaller auto --dry-run example.comotinstaller auto --type domain example.comauto asks Run? [y/N] unless you pass --yes.
Keys, updates and a failed install
Most first runs need no API key. When a tool does, otinstaller info lists the name. Put the value in ~/.otinstaller/.env, which init already created. Then:
otinstaller keys checkTo see whether a newer version exists, without installing it:
otinstaller update sherlock --check-onlyIf the computer restarted in the middle of an install, this retries it and tells you which runs to start again:
otinstaller resumeThe otinstaller exit code follows the tool. If Sherlock exits 2, otinstaller exits 2. With several tools, any failure exits 1 after a summary line. A missing required API key is a warning. The tool still runs.
Commands
| Command | What it does |
|---|---|
otinstaller list | Show every tool otinstaller knows. --installed shows only the ones on this machine. |
otinstaller search <words> | Find tools by words in the name or description. |
otinstaller info <tool> | Show how a tool is installed, what it accepts, and which API keys it uses. |
otinstaller install <tool> | Download and install a tool. --force installs it again. --yes skips the question. |
otinstaller remove <tool> | Delete an installed tool. --all deletes every installed tool. |
otinstaller run <tool> -- <args> | Run an installed tool. Arguments after -- go to the tool. |
otinstaller auto <target> | Guess the target type and run matching installed tools. |
otinstaller update <tool> | Install a newer version. --check-only reports without installing. --all checks everything installed. |
otinstaller extract <tool> | Pull emails, domains, IP addresses and URLs out of saved results. |
otinstaller diff <tool> <target> | Compare the two newest runs of one tool against one target. |
otinstaller keys check | Show which API keys are set, and which tools are missing one they require. |
otinstaller resume | Finish an install that was interrupted. Tell you which runs to start again. |
otinstaller doctor | Check Linux, Python, git, venv, and that the home folder is writable. |
otinstaller --version | Print the otinstaller version. |
list, search, info, extract, diff, update --check-only, keys check and resume accept --json if you want the same information as data.
An unknown tool name exits with an error and, when a close name exists, a "did you mean" suggestion.
otinstaller example exists and exits 2 with the message not implemented yet. Use the examples on this page instead.
Troubleshooting
Start with otinstaller doctor. It checks Linux, Python 3.10 through 3.12, git, venv, and write access to the home folder. On Debian, Ubuntu and Kali it prints sudo apt install python3-venv when venv is missing, and sudo apt install git when git is missing.
error: run 'otinstaller init' first means you have not accepted the notice. Run otinstaller init and type y.
error: confirmation needed, run with --yes means there is no keyboard to answer the question, for example inside a script. Add --yes to init, install, remove, update or auto.
error: sherlock is not installed means the run was refused. The tool name in the message is the one to install:
otinstaller install sherlockA failed install writes a log at ~/.otinstaller/logs/install-<tool>.log and deletes the half-finished folder, so the next install starts clean. Read the log if the error on screen is not enough.
otinstaller: command not found means the virtualenv is not active in this terminal. Run source .venv/bin/activate from the repository folder, then try again.
Where output goes
Every run writes a text file under results/ in the folder where you ran the command. otinstaller also writes a small .meta.json file next to it, with the time, the command, and a fingerprint of the text. There is no --output flag. To put results somewhere else, set OTINSTALLER_RESULTS_DIR before you run.
results/<tool>/<target>/
<YYYYmmdd-HHMMSS>_<tool>_<target>_<runid>.txt
<YYYYmmdd-HHMMSS>_<tool>_<target>_<runid>.meta.jsonWith --case:
results/cases/<case>/<tool>/<target>/
<YYYYmmdd-HHMMSS>_<tool>_<target>_<runid>.txt
<YYYYmmdd-HHMMSS>_<tool>_<target>_<runid>.meta.jsonThe timestamp is UTC. The run id is eight hex characters, so two runs in the same second do not overwrite each other. The target and case are lowercased, characters outside [a-z0-9._-] become _, and the result is cut at 80 characters. An empty name becomes target.
The .meta.json file records the command, tool version, target, case, start and end time, duration, exit code, status (complete, failed or interrupted), output path, byte size and SHA-256. If an API key value appears in the command, it is replaced with ***. The key itself is never written.
If you stop a run with Ctrl-C, the text already written is kept. resume does not run it again. It retries a half-finished install, and for a half-finished run it prints the command to start again. --dry-run on resume only prints that plan. Finished work is left alone.
API keys
You can ignore this until otinstaller info says a tool needs a key.
One file holds every key: ~/.otinstaller/.env. init creates it. The file mode is 600, which means only your user can read it. If the mode is looser, init tightens it.
SHODAN_API_KEY=your-key-hereOne NAME=value per line. A line starting with # is a comment. Each tool receives only the keys named in its registry entry, not the whole file. otinstaller info <tool> lists required and optional names. otinstaller keys check shows which of those names are set, which tools are missing a required key, and which single missing key would satisfy the most tools. It prints names, never values.
Security
- The env file is mode 600.
inittightens it if the mode is looser. - A tool receives only the key names it declares.
- Key values are not written to install logs or to
.meta.json. - otinstaller does not send telemetry. A tool you run may contact whatever services that tool contacts.
Updates and removal
update asks PyPI or GitHub whether a newer version exists, then asks before it reinstalls. If the tool list pins a tool to one exact version, update leaves that tool alone. --check-only prints the comparison and does not install. --json works with --check-only.
remove deletes that tool's folder and forgets it. It will not delete anything outside ~/.otinstaller/tools/. Your results stay where they are.
Uninstall
otinstaller remove deletes managed tools only. It does not uninstall the otinstaller command, and it does not delete saved results.
Installed tools, logs, API keys, and a small database that remembers what is installed live in ~/.otinstaller. If OTINSTALLER_HOME is set, they live there instead. Results live in ./results, or in OTINSTALLER_RESULTS_DIR if that is set. Those two places are separate. Deleting one does not delete the other.
To remove otinstaller itself, leave the virtualenv and delete the repository checkout you installed from. Delete ~/.otinstaller only when you also want the installed tools, logs and API keys gone.
Covered tools
The list has 38 tools. A tool is listed only after it installs in a clean virtualenv and a short check exits cleanly. That check tries --help, then --version, then -h. A person reviews the list before a release.
The input type column tells you what to pass as the target. username is a handle. email is an email address. domain is a site name such as example.com. ip is an IP address. phone is a phone number. url is a web address. name is a person's name.
Many of these tools can be misused. Read the responsible use notice before you install one.
Same two commands for every row. Replace <tool> with the name in the first column. Pass --yes on install if you do not want the confirmation question.
otinstaller install <tool>otinstaller run <tool> -- <args>| Tool | Description | Input type | GitHub |
|---|---|---|---|
aliens-eye | Search for a username across social networks. | username | arxhr007/Aliens_eye |
bbot | Recursively scan a domain or IP. | domain, ip | blacklanternsecurity/bbot |
cloud-enum | Find public cloud resources for a domain or IP. | domain, ip | initstring/cloud_enum |
crosslinked | Find employee names for an organization. | username, email, name | m8sec/CrossLinked |
ctfr | List subdomains from certificate transparency logs. | domain | UnaPibaGeek/ctfr |
dnsgen | Generate DNS name permutations. | domain | AlephNullSK/dnsgen |
dnstwist | Generate lookalike domain names. | domain, ip | elceef/dnstwist |
fierce | DNS reconnaissance for a domain. | domain, ip | mschwager/fierce |
finalrecon | Collect public information about a website. | domain, ip | thewhiteh4t/FinalRecon |
fsociety | Modular security testing framework. | domain, username, email | fsociety-team/fsociety |
ghunt | Look up a Google account from a username or email. | username, email | mxrch/GHunt |
h8mail | Search breach data for an email address. | khast3x/h8mail | |
holehe | Check whether an email is registered on other sites. | email, username | megadose/holehe |
ignorant | Check whether a phone number is registered on other sites. | phone | megadose/ignorant |
instagram-monitor | Record changes to a public Instagram profile. | username | misiektoja/instagram_monitor |
instaloader | Download public Instagram posts and metadata. | username, url | instaloader/instaloader |
ivre | Network reconnaissance framework. | domain, ip | ivre/ivre |
linkook | Find social accounts linked to a username. | username, email | JackJuly/linkook |
maigret | Search for a username across many sites. | username | soxoj/maigret |
mailaccess | Look up an email address across many sites. | KatrielMoses/MailAccess | |
nexfil | Find profiles for a username. | username | thewhiteh4t/nexfil |
onionsearch | Search onion sites. | url | megadose/OnionSearch |
openosint | Command line agent for public-information lookups. | username, email, domain | OpenOSINT/OpenOSINT |
osint-brazuca-regex | Regular expressions for Brazilian identifiers. | domain, name | osintbrazuca/osint-brazuca-regex |
paramspider | Collect archived URLs for a domain. | domain, url | devanshbatham/ParamSpider |
pywerview | Collect information from a Windows domain. | domain, username | the-useless-one/pywerview |
secator | Run security tasks from one command line. | domain, ip, username, email | freelabz/secator |
sherlock | Search for a username across social networks. | username | sherlock-project/sherlock |
sitedorks | Build search-engine queries for a site. | domain, url | Zarcolio/sitedorks |
socialscan | Check username or email use on social sites. | username, email | iojw/socialscan |
socid-extractor | Extract identifiers from a profile URL. | url, username | soxoj/socid-extractor |
spiderfoot | Collect public information for a domain, IP, username, or email. | domain, ip, username, email | smicallef/spiderfoot |
theharvester | Find emails, subdomains, and names for a domain. | domain | laramies/theHarvester |
torbot | Collect links from onion sites. | url, domain | DedSecInside/TorBot |
toutatis | Read public Instagram details from a phone number. | phone | megadose/toutatis |
user-scanner | Look up an email address or a username. | username, email | kaifcodec/user-scanner |
whatsapp-osint | Record WhatsApp presence changes for a phone number. | phone, name | jasperan/whatsapp-osint |
yark | Collect public information from YouTube. | url, username, name | Owez/yark |
auto runs a tool only when the target it detected is one of the input types in that row.
The registry
You can stop here. The sections below are reference. A first run does not need them.
The registry is the tool list. otinstaller loads the first file that exists, in this order:
- The path in
OTINSTALLER_REGISTRY, if you set that variable. ~/.otinstaller/registry.yaml, if that file exists.- The list shipped inside the package.
Some tools are left off the list on purpose. That decision is made when the list is built, not while you are using the command. Left off: phishing kits, IP grabbers, message or call bombers, credential brute-forcers, private-account bypass, dox-dump hosting, and active scanners that are not OSINT tools.
A tool marked dual-use can still be installed. It is software that is legitimate for an investigation and also easy to misuse. install prints a short reminder. info points at the notice below.
Configuration
These are environment variables. Set one in the terminal before a command when you want a different folder. Leave them unset to use the defaults.
| Variable | Default | Effect |
|---|---|---|
OTINSTALLER_HOME | ~/.otinstaller | Installed tools, logs, the install database, the acceptance record and .env. |
OTINSTALLER_RESULTS_DIR | ./results | Where run output is written. |
OTINSTALLER_REGISTRY | the list shipped with the package | Which tool list to load. |
otinstaller itself downloads tools from PyPI and GitHub. A tool you run may contact whatever services that tool contacts.
Responsible use
otinstaller init prints this notice and asks Do you accept? [y/N]. Type y to accept. This is the full text:
RESPONSIBLE USE NOTICE
otinstaller installs and runs third-party open-source tools. It does not create,
own, endorse or verify them. Many are dual-use: used for fraud investigations,
journalism, security research and compliance, but capable of misuse.
You are solely responsible for how you use these tools and for complying with all
applicable laws, including privacy, data-protection and computer-misuse laws in your
jurisdiction, and the terms of any service you query. Use them only on targets you
are authorized to investigate. Do not use them to harass, stalk or harm anyone.
Tools are provided as-is, without warranty. Their authors and the otinstaller
contributors accept no liability for misuse.Your answer is saved in ~/.otinstaller/accepted.json, along with the notice version. If the notice changes, init asks again.
Supported Linux
| Distribution | Version | How it is tested |
|---|---|---|
| Ubuntu | 22.04 LTS | Automatic tests on every change, with Python 3.10, 3.11 and 3.12 |
| Ubuntu | 24.04 LTS | Automatic tests on every change, with Python 3.10, 3.11 and 3.12 |
| Debian | 12 (bookworm) | Automatic tests in a Debian 12 container |
| Arch Linux | current rolling release | Automatic tests in the archlinux:latest image |
| Kali Linux | current release | Checked by hand before a release |
Debian and Arch use the Python that ships with that image. Kali is Debian-based, so the Debian 12 test covers the same package family. otinstaller doctor checks the machine you are on. On Debian, Ubuntu and Kali it prints sudo apt install python3-venv or sudo apt install git when one of those is missing.
Each tool is installed with pip or git, into its own virtualenv. Nothing is installed into the system Python. Tools that need Go, Rust, Node or Docker are not supported.
Authors
otinstaller is written and maintained by otinstaller contributors.
The tools in the table are separate projects. Their authors are the people named on each GitHub repository. otinstaller does not write those tools.
Contributing
From the repository folder, install the extra packages used for development, then run the same checks the automatic tests run. ruff checks style. pytest runs the tests.
pip install -e ".[dev,pipeline]"ruff check .ruff format --check .pytestA behavior change needs a test, including the case where it fails.
To propose a new tool, run the registry pipeline from the repository. It finds candidate repositories, installs each one in a clean folder, checks that --help or --version exits cleanly, and writes a draft list. That draft is not what the command loads until a person reviews it and it is merged.
To report a bad install, open an issue and include the tool name plus the log at ~/.otinstaller/logs/install-<tool>.log. To ask for a tool to be removed from the list, ask for it to be added to registry/denylist.yaml. That file can change without a code change.
Open a pull request against the otinstaller repository. Keep commit messages short and in the imperative mood, for example add config module.
License
MIT.