You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A Python port of the Emacs [gptel-agent-harness](https://github.com/beacoder/gptel-agent-harness): a minimal-dependency coding agent designed for daily use and easy customization.
5
+
**A minimal-dependency coding agent for your terminal** — FSM-driven execution, OpenAI-compatible, made for daily use and easy customization.
A Python port of the Emacs [gptel-agent-harness](https://github.com/beacoder/gptel-agent-harness): a terminal coding agent that reads your repo, plans, edits files, runs commands, and verifies its own work — with only **three runtime dependencies** (`rich`, `httpx`, `prompt_toolkit`) and any OpenAI-compatible API. No heavy frameworks, no vendor lock-in.
14
+
15
+
## Demo
6
16
7
-
-**FSM-driven agent execution with completion supervision** — the run is
8
-
driven by a finite state machine (WAIT/TOOL/TRET/SUPERVISE/DONE/ERRS/
9
-
ABRT); the model is nudged (max 2) when it tries to stop before the task
10
-
is complete; the nudge counter resets on tool calls; tool results are
11
-
sanitized so a failed call never strands the machine.
-**FSM-driven execution with completion supervision** — the run is driven by a finite state machine (`WAIT`/`TOOL`/`TRET`/`SUPERVISE`/`DONE`/`ERRS`/`ABRT`). When the model tries to stop before the task is done, it is nudged (max 2); the nudge counter resets on tool calls, and tool results are sanitized so a failed call never strands the machine.
41
+
-**Automatic retry with backoff** — transient failures (HTTP 429 / 5xx, connection errors) retry with exponential backoff + jitter, honoring `Retry-After`; retries never duplicate streamed output, Ctrl-C aborts the wait promptly, and permanent 4xx errors fail fast.
42
+
43
+
### Long conversations, no babysitting
44
+
45
+
-**Context management** — CJK-aware token estimation, per-model context windows (deepseek-v4/glm-5.2 1M, gpt-5 400k, kimi-k2.7 256k, claude 200k, ...), self-calibrating estimates from API-reported input tokens, and automatic compaction at 70% usage that summarizes the conversation and resumes with the last user request.
Tool execution mirrors gptel's `gptel--handle-tool-use`: synchronous tools (Read, Edit, Glob, ...) run one at a time in model-emitted order, while asynchronous tools (Bash, Agent) run concurrently in the background — results delivered in original call order.
52
+
53
+
### Plan before you build
54
+
55
+
-**Plan / Build modes** — plan mode is read-only except the per-session plan file; `PlanExit` switches back to build with an "execute the plan" prompt; sub-agents in plan mode get the read-only reminder.
56
+
57
+
### Sessions that survive
58
+
59
+
- Auto-saved after every response to `~/.local/share/python-agent-harness/sessions/`
60
+
- LLM-generated titles (one-shot, when the run finishes; file renamed to `<title>_<TS>.md`)
61
+
-`/restore` (with `--latest`) and `/sessions` TUI commands
62
+
63
+
### A TUI built for focus
64
+
65
+
- Rich live interface: pinned status bar (mode, context usage, spinner), streaming output, tool-result previews, pinned Todos panel (sub-agent lists labeled `sub:`), and numbered-choice prompts for Question / PlanExit.
66
+
-**Inline diff rendering** — Edit/Write calls capture a unified diff and render it red/green in the TUI, so file changes are visible without leaving the app.
67
+
-`prompt_toolkit` editor: Enter for newline, **Esc+Enter** (or Alt+Enter) to submit, **Tab completion** for slash commands and paths (`~/` and relative, Shift+Tab to cycle backwards), Up/Down history recall (persisted to `~/.local/share/python-agent-harness/input_history`), **Ctrl-D** quits, **Ctrl-C** cancels the current input or run without leaving the app — history is preserved so you can immediately ask a follow-up, and a cancelled worker can never clobber the next run's state (per-run cancellation identity).
68
+
69
+
### Extensible
70
+
71
+
-**Default agent prompts** — distinct system prompts for the main agent and sub-agents (`prompts/agent.md`, `prompts/subagent.md`), YAML frontmatter stripped, `{{SKILLS}}` filled from the discovered skill directory; the main prompt is prefixed with project context files and task-completion rules.
72
+
-**Slash commands** — `/init`, `/review`, `/explain`, plus custom commands from `prompts/commands/*.md` become TUI slash commands automatically.
73
+
74
+
## Configuration
75
+
76
+
LLM settings live in a JSON config file — no environment variables required:
`OPENAI_SUBAGENT_MODEL`, `OPENAI_SUBAGENT_BACKEND`). Use a custom
145
-
file with `--config PATH` (also settable via `PYTHON_AGENT_HARNESS_CONFIG`).
146
-
147
-
LLM request/response bodies are logged as JSON to
148
-
`/tmp/python-agent-harness-<date>-<id>.json` (override the directory with
149
-
`LLM_LOG_DIR`); the path is printed at TUI startup.
104
+
-`reasoning_effort` is passed to the API as-is (omitted when unset) — whatever your provider accepts ("low"/"medium"/"high").
105
+
- Other optional keys: `backend`, `temperature`, `max_tokens`, `timeout`, `stream` (`true` by default; `run --no-stream` overrides on the command line).
106
+
-`subagent_llm` configures the LLM for Agent-tool requests: every key is optional and unset keys inherit the main `llm`, so a cheaper/smaller model (or a different provider) can serve delegated work.
107
+
-`paths.context_path` / `paths.skill_path` override context/skill discovery — defaults are `<project>/contexts` or `~/.emacs.d/contexts` (skills: `<project>/skills` or `~/.emacs.d/skills`).
108
+
- Precedence: code defaults < config file < `OPENAI_*` env vars (env still wins if set, but nothing is required). Sub-agent settings honor `OPENAI_SUBAGENT_*` (`_BASE_URL`, `_API_KEY`, `_MODEL`, `_BACKEND`).
109
+
- Use a custom config with `--config PATH` (or `PYTHON_AGENT_HARNESS_CONFIG`).
110
+
111
+
LLM request/response bodies are logged as JSON to `/tmp/python-agent-harness-<date>-<id>.json` (override the directory with `LLM_LOG_DIR`); the path is printed at TUI startup.
150
112
151
113
## Usage
152
114
153
115
```sh
154
116
python-agent-harness run [project-dir] # interactive TUI agent
|`/restore [path\|title\|--latest]`| restore a session (title substring match) |
130
+
|`/clear`| start a fresh conversation |
131
+
|`/exit`| quit |
132
+
133
+
Custom commands from `prompts/commands/*.md` are registered as slash commands too (TUI-only — no CLI subcommand is registered for them). Tool availability differs per command: `/init` and `/review` may use all tools except `PlanExit` (hidden for the run, including for spawned sub-agents); custom commands may use everything; `compact`/`summary` run with no tools (a one-shot `chat_sync` call, like session-title generation).
0 commit comments