PTY-backed command capture with deterministic names, target-aware routing, and local provenance.
Workflow article · Original 1.x demo
NOCAP supports Linux and macOS and requires Python 3.11 or newer, uv, and
pipx 1.12 or newer.
pipx install --backend uv https://github.com/BLTSEC/NOCAP/archive/refs/tags/v2.3.0.zip
cap --version # nocap 2.3.0From a clone, run pipx install --backend uv .. A pinned installation stays on its selected
tag when cap update runs. Move releases explicitly:
pipx install --force --backend uv https://github.com/BLTSEC/NOCAP/archive/refs/tags/vX.Y.Z.zipWith no target configured, NOCAP uses the current directory:
mkdir -p ~/engagements/example
cd ~/engagements/example
cap -n local-check uname -a
cap ls
cap timelineThis captures local system information, not proof of access to another host.
For authorized target work, cap -a nmap -sV "$TARGET" routes by the effective
tool and, where needed, its action:
~/engagements/example/
├── recon/nmap_sV.txt
└── .nocap/records/<uuid>.json
The .txt file contains a short command/date header followed by the PTY stream.
The JSON record tracks identity, timing, status, route, hash, tags, renames, and
deletion state.
# Capture
cap -a nmap -sCV "$TARGET"
export KRB5CCNAME="$HOME/tickets/operator.ccache"
cap -a -n after-creds nxc smb "$TARGET" --use-kcache --shares
cap -s notes printf '%s\n' 'manual checkpoint'
cap -D -a sudo -n nmap -Pn dc01 # print the destination only
cap -- ls -la # capture a command named "ls"
# Find and inspect
cap last
cap ls
cap browse # fzf preview and selection
cap browse --print # selected absolute path
cap search --kind ports
cap inspect --verify
# Curate and export
cap tag add foothold
cap rename initial-enum
cap timeline --format md
cap review --last 10 -o review.md
# Remove
cap rm # immediately remove the last capture
cap rm --pick # multi-select, then confirmReview packets are local Markdown files. The default includes 10 captures and limits each rendered excerpt to 200 lines or 32 KiB. Inspect it before sharing.
| Concern | Behavior |
|---|---|
| Capture | Mirrors the live PTY to a .txt file created with mode 0600. |
| Naming | Unwraps launchers such as sudo, env, proxychains, shell -c, uv run, and Python modules; collisions get numeric suffixes. |
| Routing | -a routes by effective tool and selected actions for NetExec, Certipy, and Kerbrute. Target precedence is environment TACMUX_TARGET, tmux TACMUX_TARGET, TARGET, then the current directory. |
| Safety | Explicit workspaces and targets must exist and remain inside the workspace. Invalid targets never fall back to the current directory. |
| Metadata | Stores one private JSON record per capture under .nocap/records; there is no database or daemon. |
| Integrity | Records SHA-256 and file size. Verify with cap inspect --verify or cap meta verify. |
| Deletion | Removes the raw file and retains a tombstone, hidden unless --include-deleted is used. |
Use cap meta status, sync, verify, export, and prune to maintain the
record set. Back up captures and .nocap together. The
metadata lifecycle guide covers recovery and retention.
| Area | Commands |
|---|---|
| Capture | cap [options] <command>, grab |
| Find | last, ls, browse, search, summary |
| View | cat, render, open, tail; --compact is explicitly lossy |
| Manage | inspect, tag, rename, rm |
| History | timeline, review |
| Health | status, `meta status |
| Maintenance | update |
Capture selectors accept an ID prefix or a path below the active target. Where
a selector is optional, omitting it uses the newest retained capture in that
target. Run cap --help or cap <command> --help for flags.
In TACMUX 3 sessions the active metadata root is the engagement's captures/
directory, not an individual host. cap timeline, browse, and default
latest-capture selection therefore span the engagement. Use an explicit capture
ID after switching hosts or when other panes are capturing concurrently.
Configuration loads from the user file and then the active workspace file:
$XDG_CONFIG_HOME/nocap/config.toml
<workspace>/.nocap/config.toml
[capture]
auto_route = true
bell = falseNOCAP_WORKSPACE, NOCAP_AUTO, and NOCAP_BELL override the workspace,
automatic routing, and bell settings. NOCAP_ROUTE_PREFIX optionally places
capture routes below one contained prefix without changing the active metadata
root; TACMUX uses this for engagement-wide timelines with per-target folders. See
docs/config.example.toml for routes, aliases, and
bounded list, search, and review limits.
Explicit -s and positional phase directories win over configured tool routes;
configured routes win over built-in action routing. The standard capture phases
are recon, exploitation, loot, screenshots, and reports. TACMUX owns
continuous session logs; notes remains available for existing workflows.
| Tool | Role |
|---|---|
| TACMUX | Supplies target context and central pane logs. With NOCAP 2.3+, files go below captures/<route>/ and metadata stays in captures/.nocap/. |
fzf |
Enables browse, rm --pick, and review --pick. |
TACMUX 3 integration requires NOCAP 2.3 or newer. Keep pipx as the installation
manager with its uv backend; cap update uses pipx. Review the destination with
cap status and cap -D after an upgrade.
Older installations
NOCAP 2.2 removes obsolete TACMUX v1 compatibility. If you are coming from 2.0 or 2.1, these three removals affect you:
| Removed | Use instead |
|---|---|
cap logs |
cap browse for selected captures; TACMUX's engagement logs/ directory for continuous pane logs |
LOADOUT_TARGET |
TACMUX_TARGET |
Target recovery from op_* tmux session names |
Explicit TACMUX context, or TARGET for standalone routing |
Target precedence is now environment TACMUX_TARGET, tmux TACMUX_TARGET,
TARGET, then the current directory. Session names are never consulted. Set
NOCAP_WORKSPACE when using an explicit workspace; an explicit workspace with
no resolvable target fails closed rather than writing to the current directory.
Captures and .nocap metadata are unaffected. No migration step is required.
From 1.x, use Python 3.11 or newer, then run cap meta sync once in each existing target.
Back up raw captures and .nocap together. The 2.2 removals above apply as well.
Development
python3.11 -m venv .venv
. .venv/bin/activate
pip install -e '.[dev]'
pytest -q