rlm-ness
A Python implementation of Recursive Language Models, from the paper Recursive Language Models (Zhang, Kraska & Khattab), running the model's code in Node and Pyodide.
Your full input sits in a Python REPL as PROMPT. The model sees an opening
preview, then writes code to work through the input and hands pieces to
sub-agents of itself, whose answers come back as plain values in the REPL.
Install
pip install rlmness
export OPENROUTER_API_KEY=sk-or-... # or ANTHROPIC_API_KEY, DEEPSEEK_API_KEY
rlmness "How many r's are in strawberry?" --model z-ai/glm-5
That is the whole install. Nothing else is required, and no config file is needed.
Optional: rlmness --setup installs the WebAssembly sandbox the model's
code can run in — a one-time download that needs Node.js
18+. Until you run it, rlmness runs the code in a subprocess instead and
says so. It also leaves a fully commented rlmness.yaml in ~/.rlmness if
you would rather edit settings than pass flags.
Run it
rlmness "How many r's are in strawberry?" --model z-ai/glm-5
# a file as the data, the question stays separate
rlmness "Which errors repeat most, and when?" --input-file server.log --model z-ai/glm-5
# or pipe it in
cat server.log | rlmness --instruction "Which errors repeat most?" --model z-ai/glm-5
# a cheaper model for the sub-agents the root hands pieces to
rlmness "..." --model z-ai/glm-5 --sub-model minimax/minimax-m2.5
A model is never guessed for you, since it decides what a run costs: pass
--model, or set primary_agent in a config file and drop the flag.
--input-file parses by extension — .json, .jsonl, .yaml arrive as the
data they describe, anything else as text the model slices itself.
--provider anthropic or --provider deepseek switches API; each reads its
own key. Run rlmness --help for the rest.
Run rlmness with no question to open the live screen and ask from there.
Choose where the code runs
rlmness --runtime wasm "..." # default
rlmness --runtime subprocess "..."
rlmness --runtime in-process "..."
wasm(default) — a WebAssembly sandbox that blocks ordinary network and host-file access. It limits what model-written code can reach, but is not a hardened security boundary. Needsrlmness --setup; until then runs fall back tosubprocessand say so.subprocess— a separate Python process. Starts faster and can use any package you have installed, but can touch your machine. For input you trust.in-process— inside your own Python process, no isolation. For trusted code where your tools need to be live objects.
To change the default, set it once instead of passing the flag:
export RLMNESS_RUNTIME=subprocess
or put runtime: subprocess in your config. On the live screen, a picker next
to the question box switches it per question.
Keep working across questions
rlmness --session ./notes "Parse the logs and index them by service"
rlmness --session ./notes "Using that index, which service failed most?"
The second question starts with everything the first one built. Progress is
saved after every step, so an interrupted run picks up where it stopped.
--session-id keeps several sessions in one folder; --session-ephemeral
keeps one only until the program exits.
Watch a run
pip install "rlmness[tui]"
rlmness --dashboard "..." # live: agents, code, output, variables
rlmness-viewlog traces/run_x.jsonl --tui # replay a finished run
rlmness-viewlog ./notes --tui # every question a session answered
rlmness-timeline traces/run_x.jsonl # which agent ran when
Each run saves a trace under traces/ in the current folder and prints its
path at the end.
Configuration
Optional — every setting can be passed as a flag. A config file just saves repeating them:
# rlmness.yaml
primary_agent: z-ai/glm-5
sub_agent: minimax/minimax-m2.5
max_cost: 1.0
The first of these that exists is used, and flags override it for one run:
--config <path>./rlmness.yaml~/.rlmness/rlmness.yaml
Write either file yourself, or let rlmness --setup drop a commented one in
~/.rlmness for you.
Use it from Python
from rlmness import Config, make_client, solve
answer = solve(
open("server.log").read(),
make_client("openrouter"),
config=Config(primary_agent="z-ai/glm-5", sub_agent="minimax/minimax-m2.5"),
instruction="Which service failed most, and when?",
)
print(answer.output, answer.usage.cost)
solve() also takes tools= (your functions, callable in the REPL, and any
other value as a plain variable) and output_schema= (a JSON Schema the
answer must match). load_config() reads the same file the command does.
License
MIT
Metadata
Release files for rlmness 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| rlmness-0.2.1.tar.gz | 92.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| rlmness-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 193.9 kB
Release files / rlmness-0.2.1.tar.gz
| Download URL | rlmness-0.2.1.tar.gz |
|---|---|
| Size | 92.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3123385640f3ab012ad7d00252891e3d6bd4ddf917a112bdb36e9cba5020250d
|
|
BLAKE2b-256 checksum How to use checksums |
d506ec400e788e8cbc3f73acd6af4d2ec12668c0b5f2f09c19c101d14e0c78cc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.10
|
Release files / rlmness-0.2.1-py3-none-any.whl
| Download URL | rlmness-0.2.1-py3-none-any.whl |
|---|---|
| Size | 101.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d5fc5501e5964d17e82e43d5a553de773e5d2b03b439416ff1e82232e4f0006d
|
|
BLAKE2b-256 checksum How to use checksums |
f7fac38a3993d906615053b01a548298d79d3366549c7147eff0c33005e811b9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.10
|