[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-1661":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":8,"htmlUrl":8,"language":9,"languages":8,"totalLinesOfCode":8,"stars":10,"forks":11,"watchers":12,"openIssues":13,"contributorsCount":13,"subscribersCount":13,"size":13,"stars1d":12,"stars7d":12,"stars30d":14,"stars90d":13,"forks30d":13,"starsTrendScore":15,"compositeScore":16,"rankGlobal":8,"rankLanguage":8,"license":17,"archived":18,"fork":18,"defaultBranch":19,"hasWiki":18,"hasPages":18,"topics":20,"createdAt":8,"pushedAt":8,"updatedAt":21,"readmeContent":22,"aiSummary":23,"trendingCount":13,"starSnapshotCount":13,"syncStatus":24,"lastSyncTime":25,"discoverSource":26},1661,"pu","NahimNasser\u002Fpu","NahimNasser",null,"Shell",214,16,1,0,15,3,3.69,"MIT License",false,"main",[],"2026-06-12 02:00:31","\u003Cp align=\"center\">\n  \u003Cimg src=\"logo.png\" alt=\"pu.sh\" width=\"500\">\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\u003Cstrong>A zero-package-dependency coding agent under 50KB. Pronounced exactly how you think.\u003C\u002Fstrong>\u003C\u002Fp>\n\n\u003Cp align=\"center\">\u003Cem>Finally, a slop cannon small enough to fit in your pocket.\u003C\u002Fem>\u003C\u002Fp>\n\n```sh\ncurl -sL pu.dev\u002Fpu.sh -o pu.sh && chmod +x pu.sh\n.\u002Fpu.sh\n```\n\nThat's the entire install. No npm. No pip. No Docker. No Node. One shell file, common Unix tools, `curl`, `awk`, and an API key.\n\n## What\n\n```sh\n# Zero package dependencies. Literally.\ncurl -sL pu.dev\u002Fpu.sh > pu.sh && chmod +x pu.sh\n\n# First run walks you through provider, key, model, and effort.\n.\u002Fpu.sh\n\n# One-shot task.\n.\u002Fpu.sh \"find bugs in pu.sh\"\n\n# Interactive multi-turn session.\n.\u002Fpu.sh\n> write a REST API server in Go\n> now add rate limiting\n> write tests for it\n\n# Pipe agents together because we're adults.\n.\u002Fpu.sh \"write the code\" | .\u002Fpu.sh --pipe \"review it for security bugs\"\n\n# Env-only setup still works.\nOPENAI_API_KEY=sk-... AGENT_PROVIDER=openai AGENT_MODEL=gpt-5.5 .\u002Fpu.sh \"your task\"\nANTHROPIC_API_KEY=sk-ant-... AGENT_PROVIDER=anthropic AGENT_MODEL=claude-opus-4-7 .\u002Fpu.sh \"your task\"\n```\n\n## Why\n\nWe ran [30+ experiments](final_report.md) to answer a question: *what's the most portable agentic harness that can run anywhere?*\n\nThe answer is a shell script. The agent loop itself — send prompt, parse response, execute tool, append to history, repeat — is tiny. Everything else is developer experience and hardening.\n\n**Here's the thing nobody tells you:** the `node_modules` folder of a typical coding agent weighs more than the entire Doom source code. Three times over. `pu.sh` weighs less than many README files.\n\n## Features\n\n| What | How |\n|---|---|\n| **7 tools** | `bash` `read` `write` `edit` `grep` `find` `ls` — Pi-shaped surface area |\n| **Interactive REPL** | Multi-turn with memory; `\u002Fmodel` `\u002Feffort` `\u002Flogin` `\u002Flogout` `\u002Fflush` `\u002Fcompact` `\u002Fexport` `\u002Fskill:name` `\u002Fquit` |\n| **First-run login** | API-key wizard for Anthropic\u002FOpenAI, optional private `~\u002F.pu.env` save |\n| **Dual provider** | Anthropic Messages API + OpenAI Responses API |\n| **OpenAI tool loop** | Preserves `reasoning`, `function_call`, and `function_call_output` items across turns |\n| **Reasoning effort** | `AGENT_EFFORT=none|minimal|low|medium|high|xhigh|max`, gated by model support |\n| **File editing** | Surgical `oldText` → `newText` replacement; rejects empty or non-unique matches |\n| **Safer file writes\u002Fedits** | Preserves trailing newlines, uses temp files, keeps executable mode on edits |\n| **Context files** | Auto-loads `AGENTS.md` \u002F `CLAUDE.md` from cwd upward, plus global Pi agent context if present |\n| **Auto-compaction** | Summarizes older turns when approximate context budget is exceeded; `\u002Fcompact [focus]` manually compacts |\n| **Context\u002Fstatus line** | Shows cwd, git branch, token counts, context usage, provider, model, effort |\n| **!command** | `!ls -la` runs shell inline from the REPL |\n| **Prompt templates** | `\u002Fname` expands `.pi\u002Fprompts\u002Fname.md` or `~\u002F.pi\u002Fagent\u002Fprompts\u002Fname.md` |\n| **Skills** | `\u002Fskill:name` loads `SKILL.md` from local or user skill directories |\n| **Session export** | `\u002Fexport` writes markdown from `.pu-events.jsonl` |\n| **Pipe mode** | `--pipe` for clean stdout, composable with other tools\u002Fagents |\n| **Checkpoint\u002Fresume** | Writes `.pu-history.json` by default; override with `AGENT_HISTORY=file.json` |\n| **Confirmation mode** | `AGENT_CONFIRM=1` asks before every tool execution; safely denies when no TTY |\n| **Event log** | Every step logged to `.pu-events.jsonl` as structured JSONL |\n| **Regression tests** | `bash eval\u002Ftest_real.sh` runs 105 no-API behavioral tests |\n\n## What it can't do\n\nLet's be honest. The remaining gap to a production harness needs a real runtime:\n\n- No TUI (it's a shell script, not a lifestyle)\n- No streaming display (curl waits for the full response like a patient person)\n- No image input\n- No OAuth\u002Fbrowser login; API keys only\n- No native Windows support\n- No keyboard shortcuts, path completion, themes, or raw-terminal editor\n- No package manager or TypeScript plugin SDK\n- No full model registry\u002Fpricing database\n- No general JSON parser; it uses targeted `awk` parsing for provider shapes\n\n`pu.sh` is the same slop cannon but small enough to inspect end to end and know exactly where the slop is coming from.\n\n## The Size\n\n```text\npu.sh              \u003C 50 KB            █  (sh + curl + awk + common Unix tools)\nClaude Code         209 MB            ██████████████████████████\nGoose CLI           237 MB            █████████████████████████████\nPi + Node           281 MB            ███████████████████████████████████\nSWE-agent Docker    1.8 GB            ██████████████████████████████████████████████████████████████...\n```\n\n*Measured locally on macOS arm64. Current generated `pu.sh` is 49,276 bytes (48.12 KiB) by `wc -c`; the headline stays under 50 KB. Larger tools include their runtime\u002Fpackage footprints as described in [final_report.md](final_report.md).*\n\n## Configuration\n\nAll env vars. Optional `~\u002F.pu.env` is created by `\u002Flogin`\u002Ffirst run with `0600`-style permissions and parsed with a tiny allowlist loader.\n\n| Variable | Default | What |\n|---|---|---|\n| `AGENT_PROVIDER` | auto from key\u002Fmodel, else `anthropic` | `anthropic` or `openai` |\n| `AGENT_MODEL` | `claude-opus-4-7` or `gpt-5.5` | Model id |\n| `ANTHROPIC_API_KEY` | — | Anthropic API key |\n| `OPENAI_API_KEY` | — | OpenAI API key |\n| `AGENT_EFFORT` | `medium` | `none|minimal|low|medium|high|xhigh|max`; unsupported models omit effort fields |\n| `AGENT_REASONING_SUMMARY` | `auto` | OpenAI reasoning summary request: `auto|concise|detailed|off` |\n| `AGENT_THINKING` | — | Legacy\u002FAnthropic thinking hint; falls back into effort behavior |\n| `AGENT_MAX_STEPS` | `100` | Max API\u002Ftool-loop steps before stopping |\n| `AGENT_MAX_TOKENS` | `4096` | Base visible-output budget; raised for higher effort |\n| `AGENT_CONTEXT_LIMIT` | `400000` OpenAI-ish \u002F `272000` Opus-ish | Approximate context budget in bytes\u002Fchars |\n| `AGENT_RESERVE` | `16000` | Reserved context budget before compaction |\n| `AGENT_KEEP_RECENT` | `80000` | Approx bytes\u002Fchars of recent transcript to keep after compaction |\n| `AGENT_TOOL_TRUNC` | `100000` | Max non-read tool output before truncation |\n| `AGENT_READ_MAX` | `1000000` | Require offset\u002Flimit for larger file reads |\n| `AGENT_LOG_TRUNC` | `20000` | Max event-log payload before trace-only truncation |\n| `AGENT_CONFIRM` | `0` | `1` = ask before each tool call |\n| `AGENT_LOG` | `.pu-events.jsonl` | Event\u002Fdebug JSONL log file |\n| `AGENT_HISTORY` | `.pu-history.json` | Checkpoint file for automatic resume |\n| `AGENT_SYSTEM` | built-in | Custom system prompt |\n| `AGENT_PRICE_IN_PER_MTOK` \u002F `AGENT_PRICE_OUT_PER_MTOK` | `0` | Optional cost display with `--cost` |\n| `AGENT_DEBUG_API` | — | Directory to capture per-call input\u002Fresponse JSON for debugging |\n\n## Commands\n\n| Command | What |\n|---|---|\n| `\u002Fmodel [id]` | Show or switch model; guesses provider from `gpt-*`\u002F`o*`\u002F`claude-*` |\n| `\u002Feffort [level]` | Show or set reasoning effort (`none`, `low`, `medium`, `high`, `xhigh`, etc.) |\n| `\u002Freasoning [mode]` | Show or set OpenAI reasoning summaries (`auto`, `concise`, `detailed`, `off`) |\n| `\u002Flogin` | Run API-key setup wizard |\n| `\u002Flogout` | Remove `~\u002F.pu.env` and unset in-process keys |\n| `\u002Fflush` | Reset the session: clear memory\u002Fhistory, remove history metadata, and truncate event log |\n| `\u002Fcompact [focus]` | Summarize older context, optionally with focus text |\n| `\u002Fexport [file]` | Export event log to markdown |\n| `\u002Fskill:name` | Load `name\u002FSKILL.md` into the system prompt |\n| `\u002Fquit` | Exit |\n| `!cmd` | Run a shell command directly |\n| `\u002Ftemplate` | If `.pi\u002Fprompts\u002Ftemplate.md` exists, run it as a prompt |\n\n## How it works\n\n```text\n┌─────────────────────────────────────────┐\n│  You type a thing                       │\n│  ↓                                      │\n│  curl sends it to Claude\u002FGPT            │\n│  ↓                                      │\n│  Model asks for a tool                  │\n│  ↓                                      │\n│  Shell runs read\u002Fwrite\u002Fedit\u002Fbash\u002Fetc.   │\n│  ↓                                      │\n│  Result goes back to model              │\n│  ↓                                      │\n│  Model says done                        │\n└─────────────────────────────────────────┘\n```\n\nZero package dependencies. Under 50KB. 7 tools. 2 providers. 1 file.\n\nOpenAI uses `\u002Fv1\u002Fresponses` with Responses-style tools and `max_output_tokens`. Anthropic uses `\u002Fv1\u002Fmessages`. The parser is targeted `awk`, not a general JSON implementation.\n\n## How it works\n\nThe short version:\n\n```text\nprompt → provider → tool call → shell tool → tool result → repeat\n```\n\n`pu.sh` writes `.pu-history.json` for resumable model memory and `.pu-events.jsonl` for event replay\u002Fexport. Long sessions auto-compact by summarizing older transcript entries and keeping a bounded recent tail.\n\nFor details, see [How pu works](docs\u002Fhow-pu-works.md).\n\n## Testing\n\n```sh\n# No API calls, no cost. Current expected result: PASS: 105 FAIL: 0.\nbash eval\u002Ftest_real.sh\n\n# Shell syntax.\nsh -n pu.sh\n```\n\nThe current regression suite covers:\n\n- JSON escaping and targeted JSON extraction\n- Anthropic and OpenAI response parsing\n- OpenAI Responses request shape and reasoning gating\n- OpenAI tool continuation with `reasoning` + `function_call_output`\n- API-error reporting, curl transport failures, model-error hints, and non-retryable auth errors\n- first-run key sanitization and safe allowlist `~\u002F.pu.env` loading\n- default history save\u002Fresume of final assistant responses\n- context compaction invariants\n- tool truncation\n- edit uniqueness\u002Fmode preservation and actionable edit-failure guidance\n- `grep`\u002F`find` noisy-directory exclusions and `\u002Feffort` command\n- trailing-newline preservation for `write`\u002F`edit`\n- `read limit:0`\n- spinner quietness on non-TTY stderr\n\n## The bugs we found so you don't have to\n\n1. **`set -e` is a serial killer.** `[ -f file ] && do_thing` returns 1 when the file doesn't exist. `set -e` treats that as fatal and silently kills your script. We use `set -u`, not `set -e`.\n2. **macOS sed ≠ GNU sed.** The classic multiline sed trick breaks on BSD sed. Use `awk`.\n3. **jq was a dependency.** We wrote targeted `awk` JSON extraction to keep install at zero.\n4. **Heredocs don't survive JSON reliably.** The system prompt steers models to the `write` tool instead.\n5. **OpenAI tool calling is not Chat Completions anymore.** For reasoning + tools, `pu.sh` uses Responses API, carries `reasoning` items forward, and sends `function_call_output` items.\n6. **Shell command substitution eats trailing newlines.** `write` and `edit` use sentinel capture to preserve final `\\n`.\n7. **Generic status spam is worse than silence.** If the model doesn't provide a real pre-tool preamble, `pu.sh` just prints the actual tool call instead of `Inspecting with tools...` forever.\n\n## Prior art & credits\n\n`pu.sh` is a derived work, and we want to be loud about it. The system prompt structure, 7-tool surface (`bash` `read` `write` `edit` `grep` `find` `ls`), exact-text editing model, context-file convention, and skill\u002Ftemplate ideas are inspired by **[Pi](https:\u002F\u002Fpi.dev\u002F)**. Huge thanks and respect to the Pi team.\n\nWe [compare against Pi](eval\u002FCOMPARISON.md) feature-by-feature. Pi wins on extensibility, TUI, providers, safety, and production polish. `pu.sh` wins on portability and inspectability.\n\n## FAQ\n\n**Is this production-ready?**\nIt's called `pu.sh`. It's an under-50KB slop cannon that talks to LLM APIs via `curl`. You tell me.\n\n**Should I use this instead of Pi\u002FClaude Code\u002FCursor?**\nFor daily coding, probably not. Use a real tool. For CI\u002FCD, containers, edge boxes, quick scripts, or understanding how agents actually work — `.\u002Fpu.sh` and see what happens.\n\n**How do I pronounce it?**\nHowever makes your coworkers the most uncomfortable.\n\n**Did you really name a coding agent after feces?**\nIt's `pu.sh`. As in push. As in `.\u002Fpu.sh \"deploy to prod\"`. The fact that it sounds like something else is entirely coincidental and we are very serious engineers.\n\n**Did an AI write this?**\nAn AI and a human ran experiments, argued with shell, broke OpenAI schemas, fixed them, and learned once again that the real production incident was `set -e` all along.\n\n## License\n\nMIT — see [LICENSE](LICENSE). It's under 50KB. Go nuts.\n","pu.sh 是一个零依赖的编码代理工具，体积小于50KB。它通过Shell脚本实现，仅依赖于常见的Unix工具如`curl`和`awk`以及API密钥即可运行，无需安装额外的包或环境。核心功能包括交互式的多轮对话、支持多种编程任务（如代码编写、审查等），并且能够与多个AI服务提供商（如Anthropic和OpenAI）集成。此外，它还提供了文件编辑时的安全措施，比如保留尾随换行符、使用临时文件等。适用于需要快速部署且对系统资源占用要求极低的开发场景中，特别是在那些无法或不便安装复杂软件栈的环境中表现尤为突出。",2,"2026-06-11 02:45:17","CREATED_QUERY"]