Custom REPL commands¶
A Python script can add commands to the REPL. They run inside the REPL’s own session rather than attaching a second debugger, and they reach the target through the same API as the Python SDK.
Put a *.py file in ~/.ntoseye/commands/. Scripts load at startup, and reload-scripts picks up edits without restarting. Custom commands need an ntoseye with Python in it: the command the Python package installs (uv tool install ntoseye or pipx install ntoseye) and cargo install builds both have it. The prebuilt release archives have no Python; they list the scripts they skipped and how to get a build that runs them.
A first command¶
import ntoseye.repl as repl
@repl.command("pscount", "Count running processes.\n(usage: pscount [-v])")
def pscount(dbg: repl.Debugger, *args: str):
processes = dbg.processes
print(f"{len(processes)} processes")
if args and args[0] == "-v":
for process in processes:
print(f" {process.eprocess:#x} {process.pid:>6} {process.name}")
This is examples/commands/pscount.py. After copying it into ~/.ntoseye/commands/, pscount -v lists every process.
The help text is the second argument.
.hhlists custom commands under “python commands” with the first line of their help, and.hh pscountprints all of it.Arguments arrive after
dbgas strings, split and quoted the same way as a built-in command’s.dbgis a borrowedntoseye.Debuggerfor the REPL’s session. It is valid only until the command returns: keeping it (or an object read through it) in a global and using it later raises.
Tab completion¶
Keyword arguments to repl.command bind a parameter, by name, to one of the completion markers in ntoseye.repl, so tab completes that argument the way the built-in commands do:
@repl.command("pinfo", "Show a process.\n(usage: pinfo <process>)", target=repl.Process)
def pinfo(dbg: repl.Debugger, target: str):
...
The markers are Process, Symbol, Expression, Type, Driver, Thread, Vcpu, Breakpoint, and Alias. A parameter without a marker gets no completion.
Registering without the decorator¶
repl.register_command(name, help, fn, strategies) is what the decorator calls: strategies lists one completion name per parameter after dbg ("process", "symbol", …, or "none"). Outside the REPL, for example when a command script is run with plain python, it raises instead of registering.
More scripts are in examples/commands/.