Repository navigation
Proxima v1.6.0
What's changed
Added
- Official plugin distribution (SPECS §21.1) —
proxima plugin list | install <name> | remove <name> | update, and/pluginin the REPL. Plugins install from a published catalogue into~/.proxima/plugins/, making them available in every project.pluginis intercepted before flag parsing, because the main parser treats the first positional as a natural-language task — without that,proxima plugin install xwas silently sent to the model as a prompt - Install safety — SHA-256 verified against the catalogue before anything reaches disk, HTTPS-only downloads, and zip-slip rejected: any archive entry resolving outside the plugin directory aborts the install, with validation and extraction sharing one separator-normalised path so Windows-style
..\..\xentries cannot slip past a POSIX check. Plugin names must be a single path component, soplugin remove ../../Documentsis refused rather than deleting an arbitrary directory — and both the CLI and/pluginreport that rejection instead of propagating it, since an uncaught throw ended the REPL session over a typo.plugin.json's declaredexecutableis contained the same way: a declared../../victim.shwould otherwisechmod +xa file outside the plugin, whichPluginLoaderwould then follow and register under the malicious descriptor's name and risk level. An update moves the existing install aside and restores it if the staged rename fails, so a transient error cannot uninstall a working plugin. Execute permissions are restored from the descriptor's declaredexecutable— matching only*.shleft an extensionless entry point unrunnable. Zip-slip and the name/permission handling are not in SPECS §21.1 — a checksum proves the archive matches the catalogue, not that its contents are safe ~expansion in plugin directories (PluginLoader.resolvePluginDir) — config values come from YAML and never pass through a shell, so~/.proxima/pluginspreviously resolved to<workingDir>/~/.proxima/pluginsscripts/build_catalog.py— packages eachplugins/<name>/intoplugin-<name>.zip, computes checksums, and writescatalog.json; wired intorelease.yml, with a descriptor-validation step added toci.yml- Provider and tool test coverage —
AnthropicProvider(33) andOllamaProvider(25) had no HTTP-level tests at all despite Anthropic being the default provider, andtransport.darthad none despite existing to prevent a specific bug class. Plusrun_tests(23),write_plan(10),delegate(7), the plugin installer (22), and the plugin CLI (15)
Fixed
- CI pinned to Dart 3.11.1 — both workflows used
sdk: stable, so a formatter change between SDK releases faileddart format --set-exit-if-changedon all three platforms for code that formatted cleanly against the SDK named inpubspec.yaml. The pin makes formatting reproducible locally; raise it and the pubspec constraint together - Spinning detection interrupted legitimate exploration —
isSpinningfired on any six consecutive read-only calls without checking whether they targeted the same thing, so reading six different files on a small project was indistinguishable from looping. Observed twice in one session on a six-file project, blocking the task both times. It now also requires the window to be repetitive (fewer than four distinct call fingerprints). Three existing tests had encoded the wrong behaviour and were corrected /filesignored reads — it matched onlywrite_file/patch_file/delete_file, so it reported "No files accessed this session" after reading a file, while documented as "files read or written"- The write critic could not see the file path — it received only the tool name and content, so it reported changes as "lacking a file path" while the confirmation panel displayed that path directly above
--resume <missing-id>failed silently — an unknown session id started a blank session with no message, so a typo looked like a successful resume with lost history- OpenAI bypassed its own transport helper — a previous change replaced
transportPost/transportSendwith raw client calls, and the streaming retry had no error guard at all, so a transport failure there escaped as a rawClientException. This is the exact bug classtransport.dartexists to prevent - Inconsistent error classification across providers — Anthropic mapped 403 to
unknownrather thanauth, so a revoked key triggered a pointless fallback to a secondary that would also fail (FallbackProvidertreatsauthas non-retryable). Ollama mapped everything tounknown, leaving retry logic nothing to act on for a rate-limited remote instance. All three providers now classify identically write_planthrew a rawTypeErroron a missing or non-stringcontent, escaping theToolErrortaxonomy the agent loop uses to classify failures
Installation
macOS / Linux — install script
curl -fsSL https://raw.githubusercontent.com/jizzel/proxima/main/install.sh | shmacOS (Apple Silicon + Intel via Rosetta 2)
curl -fsSL https://github.com/jizzel/proxima/releases/download/v1.6.0/proxima-macos-arm64 \
-o /usr/local/bin/proxima && chmod +x /usr/local/bin/proximaLinux (x86_64)
curl -fsSL https://github.com/jizzel/proxima/releases/download/v1.6.0/proxima-linux-x64 \
-o /usr/local/bin/proxima && chmod +x /usr/local/bin/proximaWindows (x86_64) — PowerShell
irm https://raw.githubusercontent.com/jizzel/proxima/main/install.ps1 | iexOr download proxima-windows-x64.exe below and add it to a directory on your PATH.