{"id":47206872,"url":"https://github.com/rawwerks/ypi","last_synced_at":"2026-03-13T14:06:39.666Z","repository":{"id":338078661,"uuid":"1154014971","full_name":"rawwerks/ypi","owner":"rawwerks","description":"A recursive coding agent inpired by RLMs","archived":false,"fork":false,"pushed_at":"2026-03-05T06:23:47.000Z","size":1771,"stargazers_count":156,"open_issues_count":5,"forks_count":17,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-03-05T11:23:25.178Z","etag":null,"topics":["agents","cli","openclaw","pi","recursion","rlm"],"latest_commit_sha":null,"homepage":"https://ypi.sh","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rawwerks.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-02-09T23:25:20.000Z","updated_at":"2026-03-05T01:34:22.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/rawwerks/ypi","commit_stats":null,"previous_names":["rawwerks/ypi"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/rawwerks/ypi","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rawwerks%2Fypi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rawwerks%2Fypi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rawwerks%2Fypi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rawwerks%2Fypi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rawwerks","download_url":"https://codeload.github.com/rawwerks/ypi/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rawwerks%2Fypi/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30467905,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-13T11:00:43.441Z","status":"ssl_error","status_checked_at":"2026-03-13T11:00:23.173Z","response_time":60,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agents","cli","openclaw","pi","recursion","rlm"],"created_at":"2026-03-13T14:06:38.998Z","updated_at":"2026-03-13T14:06:39.655Z","avatar_url":"https://github.com/rawwerks.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ypi\n\n[![npm](https://img.shields.io/npm/v/ypi?style=flat-square)](https://www.npmjs.com/package/ypi)\n\n**ypi** — a recursive coding agent built on [Pi](https://github.com/badlogic/pi-mono).\n\nNamed after the [Y combinator](https://en.wikipedia.org/wiki/Fixed-point_combinator#Y_combinator) from lambda calculus — the fixed-point combinator that enables recursion. `ypi` is Pi that can call itself. (`rpi` already has another connotation.)\n\nInspired by [Recursive Language Models](https://github.com/alexzhang13/rlm) (RLM), which showed that an LLM with a code REPL and a `llm_query()` function can recursively decompose problems, analyze massive contexts, and write code — all through self-delegation.\n\n## The Idea\n\nPi already has a bash REPL. We add one function — `rlm_query` — and a system prompt that teaches Pi to use it recursively. Each child gets its own [jj](https://martinvonz.github.io/jj/) workspace for file isolation. That's the whole trick.\n\n```\n┌──────────────────────────────────────────┐\n│  ypi (depth 0)                           │\n│  Tools: bash, rlm_query                  │\n│  Workspace: default                      │\n│                                          │\n│  \u003e grep -n \"bug\" src/*.py                │\n│  \u003e sed -n '50,80p' src/app.py \\          │\n│      | rlm_query \"Fix this bug\"          │\n│            │                             │\n│            ▼                             │\n│    ┌────────────────────────────┐        │\n│    │  ypi (depth 1)            │        │\n│    │  Workspace: jj isolated   │        │\n│    │  Edits files safely       │        │\n│    │  Returns: patch on stdout │        │\n│    └────────────────────────────┘        │\n│                                          │\n│  \u003e jj squash --from \u003cchild-change\u003e       │\n│  # absorb the fix into our working copy  │\n└──────────────────────────────────────────┘\n```\n\n---\n\n## Using ypi\n\n### Install\n\n```bash\n# npm (global)\nnpm install -g ypi\n\n# or run without installing\nnpx ypi \"What does this repo do?\"\nbunx ypi \"What does this repo do?\"\n\n# or curl\ncurl -fsSL https://raw.githubusercontent.com/rawwerks/ypi/master/install.sh | bash\n\n# or manual\ngit clone https://github.com/rawwerks/ypi.git \u0026\u0026 cd ypi\ngit submodule update --init --depth 1\nexport PATH=\"$PWD:$PATH\"\n```\n\n### Run\n\n```bash\n# Interactive\nypi\n\n# One-shot\nypi \"Refactor the error handling in this repo\"\n\n# Different model\nypi --provider anthropic --model claude-sonnet-4-5-20250929 \"What does this codebase do?\"\n```\n\n### How It Works\n**Three pieces** (same architecture as Python RLM):\n| Piece | Python RLM | ypi |\n|---|---|---|\n| System prompt | `RLM_SYSTEM_PROMPT` | `SYSTEM_PROMPT.md` |\n| Context / REPL | Python `context` variable | `$CONTEXT` file + bash |\n| Sub-call function | `llm_query(\"prompt\")` | `rlm_query \"prompt\"` |\n**Recursion:** `rlm_query` spawns a child Pi process with the same system prompt and tools. The child can call `rlm_query` too:\n\n```\nDepth 0 (root)    → full Pi with bash + rlm_query\n  Depth 1 (child) → full Pi with bash + rlm_query, own jj workspace\n    Depth 2 (leaf) → full Pi with bash, but no rlm_query (max depth)\n```\n\n**File isolation with jj:** Each recursive child gets its own [jj workspace](https://martinvonz.github.io/jj/latest/working-copy/). The parent's working copy is untouched. Review child work with `jj diff -r \u003cchange-id\u003e`, absorb with `jj squash --from \u003cchange-id\u003e`.\n\n### Why It Works\n\nThe design has three properties that compound:\n\n1. **Self-similarity** — Every depth runs the same prompt, same tools, same agent. No specialized \"scout\" or \"planner\" roles. The intelligence is in *decomposition*, not specialization. The system prompt teaches one pattern — size-first → search → chunk → delegate → combine — and it works at every scale.\n\n2. **Self-hosting** — The system prompt (SECTION 6) contains the full source of `rlm_query`. The agent reads its own recursion machinery. When it modifies `rlm_query`, it's modifying itself. This isn't a metaphor — it's the actual execution model.\n\n3. **Bounded recursion** — Five concentric guardrails (depth limit, PATH scrubbing, call count, budget, timeout) guarantee termination. The system prompt also installs *cognitive* pressure: deeper agents are told to be more conservative, preferring direct action over spawning more children.\n\n4. **Symbolic access** — Anything the agent needs to manipulate precisely is a file, not just tokens in context. `$CONTEXT` holds the data, `$RLM_PROMPT_FILE` holds the original prompt, and hashline provides line-addressed edits. Agents `grep`/`sed`/`cat` instead of copying tokens from memory.\n\n### Guardrails\n\n| Feature | Env var | What it does |\n|---------|---------|-------------|\n| Budget | `RLM_BUDGET=0.50` | Max dollar spend for entire recursive tree |\n| Timeout | `RLM_TIMEOUT=60` | Wall-clock limit for entire recursive tree |\n| Call limit | `RLM_MAX_CALLS=20` | Max total `rlm_query` invocations |\n| Model routing | `RLM_CHILD_MODEL=haiku` | Use cheaper model for sub-calls |\n| Depth limit | `RLM_MAX_DEPTH=3` | How deep recursion can go |\n| jj disable | `RLM_JJ=0` | Skip workspace isolation |\n| Plain text | `RLM_JSON=0` | Disable JSON mode (no cost tracking) |\n| Tracing | `PI_TRACE_FILE=/tmp/trace.log` | Log all calls with timing + cost |\n\nThe agent can check spend at any time:\n\n```bash\nrlm_cost          # \"$0.042381\"\nrlm_cost --json   # {\"cost\": 0.042381, \"tokens\": 12450, \"calls\": 3}\n```\n\n### Pi Compatibility\n\nypi is a thin layer on top of Pi. We strive not to break or duplicate what Pi already does:\n\n| Pi feature | ypi behavior | Tests |\n|---|---|---|\n| **Session history** | Uses Pi's native `~/.pi/agent/sessions/` dir. Child sessions go in the same dir with trace-encoded filenames. No separate session store. | G24–G30 |\n| **Extensions** | Passed through to Pi. Children inherit extensions by default. `RLM_EXTENSIONS=0` disables. | G34–G38 |\n| **System prompt** | Built from `SYSTEM_PROMPT.md` + `rlm_query` source, written to a temp file, passed via `--system-prompt` (file path, never inlined as shell arg). | T8–T9 |\n| **`-p` mode** | All child Pi calls run non-interactive (`-p`). ypi never fakes a terminal. | T3–T4 |\n| **`--session` flag** | Used when `RLM_SESSION_DIR` is set; `--no-session` otherwise. Never both. | G24, G28 |\n| **Provider/model** | Never hardcoded. ypi and `rlm_query` use Pi's defaults unless the user sets `RLM_PROVIDER`/`RLM_MODEL`. | T14, T14c |\n\nIf Pi changes how sessions or extensions work, our guardrail tests should catch it.\n\n---\n\n## Contributing\n\n### Project Structure\n\n```\nypi/\n├── ypi                    # Launcher: sets up env, starts Pi as recursive agent\n├── rlm_query              # The recursive sub-call function (Pi's analog of rlm llm_query())\n├── SYSTEM_PROMPT.md       # Teaches the LLM to be recursive + edit code\n├── AGENTS.md              # Meta-instructions for the agent (read by ypi itself)\n├── Makefile               # test targets\n├── tests/\n│   ├── test_unit.sh       # Mock pi, test bash logic (no LLM, fast)\n│   ├── test_guardrails.sh # Test guardrails (no LLM, fast)\n│   └── test_e2e.sh        # Real LLM calls (slow, costs ~$0.05)\n├── pi-mono/               # Git submodule: upstream Pi coding agent\n└── README.md\n```\n\n### Version Control\n\nThis repo uses **[jj](https://martinvonz.github.io/jj/)** for version control. Git is only for GitHub sync.\n\n```bash\njj status                    # What's changed\njj describe -m \"message\"     # Describe current change\njj new                       # Start a new change\njj bookmark set master       # Point master at current change\njj git push                  # Push to GitHub\n```\n\n**Never use `git add/commit/push` directly.** jj manages git under the hood.\n\n### Testing\n\n```bash\nmake test-fast         # unit + guardrails\nmake test-extensions   # extension compatibility with installed pi\nmake pre-push-checks   # shared local/CI gate (recommended before push)\nmake test-e2e          # real LLM calls, costs money\nmake test              # all of the above\n```\n\nInstall hooks once per clone to run checks automatically on git push:\n```bash\nmake install-hooks\n```\n\nRelease/update helper:\n```bash\nmake release-preflight   # same checks + upstream dry-run in one command\nmake land                # deterministic-ish landing helper\n```\n\n**Before any change to `rlm_query`:** run `make test-fast`. After: run it again. `rlm_query` is a live dependency of the agent's own execution — breaking it breaks the agent.\n\nCI helper commands:\n```bash\nmake ci-status N=15      # recent workflow runs\nmake ci-last-failure     # dump latest failing workflow log\n```\n\n\n### History\n\nypi went through four approaches before landing on the current design:\n\n1. **Tool-use REPL** (exp 010/012) — Pi's `completeWithTools()`, ReAct loop. 77.6% on LongMemEval.\n2. **Python bridge** — HTTP server between Pi and Python RLM. Too complex.\n3. **Pi extension** — Custom provider with search tools. Not true recursion.\n4. **Bash RLM** (`rlm_query` + `SYSTEM_PROMPT.md`) — True recursion via bash. **Current approach.**\n\nThe key insight: Pi's bash tool **is** the REPL. `rlm_query` **is** `llm_query()`. No bridge needed.\n\n---\n\n## See Also\n\n- [Pi coding agent](https://github.com/badlogic/pi-mono) — the underlying agent\n- [Recursive Language Models](https://github.com/alexzhang13/rlm) — the library that inspired this\n- [rlm-cli](https://github.com/rawwerks/rlm-cli) — Python RLM CLI (budget, timeout, model routing)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frawwerks%2Fypi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frawwerks%2Fypi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frawwerks%2Fypi/lists"}