A streaming terminal REPL for any agent.
Project description
partnuh
A streaming terminal REPL for any agent.
partnuh gives an existing agent — smolagents, an OpenAI-compatible chat model,
or anything you can wrap — a fast, multi-line terminal chat with token
streaming. It doesn't build agents; it gives the one you have a nice place to
talk.
import partnuh
agent = partnuh.AgentSpec(name="Private Caller", model="openai/gpt-5.4-nano").build()
partnuh.run(agent)
Run the example locally (from a checkout)
Install the package into a virtualenv in editable mode, then run the example —
examples/basic_agent.py, a complete agent CLI in a few lines:
cd partnuh
python3 -m venv .venv
.venv/bin/pip install -e ".[openai,dotenv]" # or ".[all]"
cp .env.template .env # add your OPENROUTER_API_KEY
.venv/bin/python examples/basic_agent.py # interactive
.venv/bin/python examples/basic_agent.py "hello" # one-shot
It auto-loads .env. See the comments in the file for how each part maps to the
library.
Install (as a dependency)
pip install partnuh # core (bring your own agent)
pip install "partnuh[openai]" # + OpenAI/OpenRouter chat backend
pip install "partnuh[smolagents]" # + smolagents adapter
pip install "partnuh[all]"
Use
A chat model over OpenRouter (no framework):
import partnuh
agent = partnuh.AgentSpec(
name="Private Caller",
model="openai/gpt-5.4-nano", # OpenRouter model id
backend="openrouter", # uses $OPENROUTER_API_KEY
).build()
partnuh.run(agent)
Wrap a smolagents agent (tool calling works):
import os, partnuh
from smolagents import OpenAIServerModel, ToolCallingAgent, tool
@tool
def add(a: int, b: int) -> int:
"Add two integers.\n\nArgs:\n a: first\n b: second"
return a + b
model = OpenAIServerModel(model_id="openai/gpt-5.4-nano",
api_base="https://openrouter.ai/api/v1",
api_key=os.environ["OPENROUTER_API_KEY"])
smol = ToolCallingAgent(tools=[add], model=model, stream_outputs=True)
agent = partnuh.from_smolagents(smol, name="Private Caller")
partnuh.run(agent)
Ready-to-run command (after pip install "partnuh[openai,dotenv]"):
export OPENROUTER_API_KEY=sk-or-...
partnuh # interactive
partnuh "what's 2+2?" # one-shot
In the REPL
- Enter submits, Shift+Enter inserts a newline (works across terminals — see below). Backspace on a blank line joins back to the previous line.
/toolslist tools ·/resetclear history ·/help·/quit
Configuring behavior
from partnuh import CliConfig
partnuh.run(agent, config=CliConfig(
stream_speed=0.0, # 0 = as-fast-as-tokens-arrive; 1.0 = slow typewriter
show_tool_calls=True, # render the tool-call markers
banner=True,
commands={"clear": lambda d, args: __import__("os").system("clear")},
))
How it works (ports & adapters)
There is no universal in-process agent object shared across frameworks, so
partnuh defines a tiny contract and ships adapters:
CliAgentprotocol —name,model,tools, andstream(prompt, session_id) -> Iterator[Event].Eventunion —TextDelta,ToolCallStarted,ToolResult,Error,Done. Every adapter translates its framework's native stream into these; a barestris treated as aTextDelta.- Adapters —
from_openai,from_smolagents,from_callable. Add your own by yieldingEvents. Pacer— renders the event stream to the terminal with optional speed control.
The Shift+Enter trick
Terminals encode Shift+Enter differently, and prompt_toolkit's default collapses
the common Ghostty/xterm encoding into plain Enter (so it submits instead of
adding a newline). partnuh registers every known Shift+Enter escape sequence
(\x1b[27;2;13~, kitty's \x1b[13;2u, …) and maps it to "insert newline" — no
terminal config required.
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file partnuh-0.0.1.tar.gz.
File metadata
- Download URL: partnuh-0.0.1.tar.gz
- Upload date:
- Size: 15.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bb0068f3324fa73145e4b632ec2fcea2591e927f49e76a28933ef6069e16d961
|
|
| MD5 |
7121143f0917850ff7f5740c68fbe6b7
|
|
| BLAKE2b-256 |
a3a4d66c5270182a55dc761b24d755c6410ec0b26256ebbaa1dda458abf98d58
|
File details
Details for the file partnuh-0.0.1-py3-none-any.whl.
File metadata
- Download URL: partnuh-0.0.1-py3-none-any.whl
- Upload date:
- Size: 17.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1aac1ac223a8a9ef08c3b756ed0333fe27b2da4378e8b88ae6fa591245fcaed4
|
|
| MD5 |
a4ae54aafd57905ac8fcf00f86913d3f
|
|
| BLAKE2b-256 |
b0d6d39a1603b7d822469e513442d1dc117c4795450424f71b8e03dd0dca6bf7
|