Skip to content

Releases: lavindeep/ShellPilot

v0.11.1 — dynamic tool guide and memory store caps

Choose a tag to compare

@lavindeep lavindeep released this 04 Jul 19:18
5fee884

A focused patch release: the system prompt now carries a self-consistent tool guide, and persistent memory is capped so it stays selective.

Dynamic tool guide

The system prompt gains a compact Tool guide block rendered directly from the session's registered tool definitions, so it can never drift from the actual toolset:

  • Optional tools (memory_*, web_*, skill_read) are listed only when they are registered for the session.
  • update_plan appears only while a plan is active or blocked, preserving the proposal-vs-execution split.
  • Roughly 82 tokens for the default toolset; the block shows up in /context like any other.

This bumps PROMPT_VERSION to 6.

Memory store caps

  • memory.json (global and project, each separately) is now capped at 1800 serialized characters. Writes that would exceed the cap are rejected with a clear instruction to forget or compact existing entries — stored memory stays selective instead of relying on prompt truncation.
  • The cap ratchets: stores that predate the cap and exceed it can always shrink (/memory forget keeps working, including for minified legacy files), while growth stays rejected until the store complies.
  • /memory compact is now atomic across stores — every replacement is validated before any file is written, so a rejected optimization can no longer partially apply.
  • /memory add, /memory forget, and /memory compact report cap rejections with a friendly message instead of failing opaquely.

Scoped memory

  • The injected memory block now groups global and project preferences into distinct sections.
  • memory_propose_update documents the global-vs-project scope policy (what belongs where, what should never be stored) in its tool description.

Quality

  • 1625 tests (up from 1610), ruff + mypy --strict green, CI green on Python 3.11 and 3.14.
  • New coverage for legacy over-cap stores, ratchet semantics, atomic compact rejection, grouped rendering, and tool-guide composition.
  • Validated in a live session before merge.

Full Changelog: v0.11.0...v0.11.1

v0.11.0 — the full-screen app

Choose a tag to compare

@lavindeep lavindeep released this 02 Jul 20:15
f85f418

ShellPilot v0.11.0 — the full-screen app

ShellPilot now opens as a persistent full-screen terminal app on an interactive TTY: a scrolling transcript pane, a framed modal input dock, and a pinned status bar. The classic line-based REPL remains available via --legacy-ui (or SHELLPILOT_UI=legacy) and shares the same renderers.

The app

  • Modal input dock — the border says what it is asking: faint while idle, amber ╭─ approve? ─╮ for a pending approval, red ╭─ type "run" to execute ─╮ for high-risk actions.
  • Type-ahead queue — keep typing while a turn runs; the staged message fires at turn end, and Up-arrow recalls it.
  • Worker-thread turns — streaming, scrolling, and Ctrl-C stay live mid-generation.
  • Clean cancellation — Ctrl-C aborts a generation mid-stream, kills a running command's process group immediately, or declines the pending approval; conversation history and the on-disk session roll back consistently.
  • Thinking trails — reasoning models stream their thinking into a live, collapsible trail (display-only, never fed back).
  • Slash menu and completion — a filtered command menu above the dock, Tab path completion for /cwd set, /attach, and /export, and background-cached model-name completion for /model use.
  • Diffs and tool calls — approval previews show the entire diff (click or Ctrl-O to expand/collapse); tool calls render by subject; !<cmd> output is captured into the transcript.
  • Status bar — workspace, model, profile, git branch, locality, and context usage, always visible.

Correctness and hardening

  • Session transcripts now carry reconciliation records: a mid-batch approval decline and a mid-tool cancel both repair the on-disk transcript, so --resume never replays lost or half-finished work.
  • A plain approval decline ends the turn (and pauses an active plan) instead of letting the model immediately retry; steering via [e]dit continues as before.
  • Worker-action failures map through the leak-free error path — raw upstream response bodies never reach the terminal.
  • User paths in /cwd and /model error messages are markup-escaped; tilde completion degrades gracefully when no home directory can be resolved.
  • The test suite (1,610 tests) is hermetic against ambient terminal/color environment and machine-specific home directories; CI runs the full gate on Python 3.11 and 3.14.

Docs

  • README rewritten from the ground up for v0.11.0.
  • DESIGN.md updated throughout §31 (app shell, threading, approvals, cancellation, dock, menu, trails) plus the decline/reconciliation semantics.

Validated live on local and cloud models during development; the line-based REPL remains the supported path for non-TTY and SSH use.

v0.10.1 — post-v0.10.0 hardening and cleanup

Choose a tag to compare

@lavindeep lavindeep released this 27 Jun 18:11
0e88735

v0.10.1 — post-v0.10.0 hardening and cleanup

A patch release on top of v0.10.0. Resolves a wave of external-review logic and security findings, adds robustness fixes, and lands behavior-preserving internal cleanups. No model-facing behavior change — a default localhost session is unchanged.

External-review logic & security fixes

  • Classifier — escalate git mutating verbs and option-encoded paths off auto-run.
  • Command output — hard-bounded per read (chunked readline; the final chunk is sliced to the remaining budget so total capture never exceeds the cap).
  • HTTP egresstrust_env=False on every httpx client (ollama / fetch / search) so an ambient proxy env var can't reroute traffic.
  • Secret redaction — broadened to key-named, JSON-shaped, and prefixed keys (OPENAI_API_KEY, DB_PASSWORD, MY_API_KEY).
  • Planner — finalize on a skipped final step; pin the artifact path to the plan workspace.
  • Ollama — reject truncated streams (no done sentinel); typed OllamaResponseErrors on malformed or wrong-shaped responses, including streaming chunk shapes (non-dict chunk / message / tool_calls); a non-dict element inside a valid tool_calls list is skipped, not raised.
  • Session --resume — reject any session id whose resolved parent escapes the sessions directory (path-traversal guard).
  • CLI — guard slash / manual-shell Ctrl+C turns; validate --resume before preload.
  • Misc — memory rebuild on /cwd; image-token gate; write-preview placeholder; reserved-name union; uddg redirect-scheme validation; max_results clamp; web fetch no longer flags exact-byte-limit bodies as truncated.

Cleanups (behavior-preserving)

  • Dead-code removal, /api/show probe + skill-decision dedup, loader path/traversable dedup, and import/constant hygiene. No behavior change.

Verification

  • Phase gate green: ruff check, ruff format --check, mypy shellpilot --strict, pytest1255 passing.
  • TDD red-first per fix; each fix cluster independently reviewed.
  • Docs updated in step: __version__ → 0.10.1, README roadmap, DESIGN status line.

v0.10.0 — Security hardening + opt-in cloud models

Choose a tag to compare

@lavindeep lavindeep released this 25 Jun 18:52
4c1a68a

v0.10.0 is a security-critical release: repo-wide hardening, opt-in cloud models behind an explicit consent boundary, richer workflow skills, and UI polish. Local-first by default — nothing leaves your machine unless you opt into a cloud model and consent per session.

Security hardening

  • Command-classifier read-path tightened: path-qualified executables, non-benign git globals, and pytest now require approval; reader execs honor the workspace boundary and sensitive-read gates.
  • Terminal output sanitized for control/ANSI sequences at every sink; model-controlled fields (plan goal/steps) sanitized.
  • Two-tier egress/safety config invariant: structural keys (model.options, skills.enabled) are config-file-only; egress/safety keys (tools.web, model.base_url, runtime.security_profile, model.allow_cloud) are high-stakes — settable via config.toml or a confirm-gated /config set, never via an env var.
  • Project AGENTS.md gated behind trust-on-first-use (re-prompts on content change).
  • DNS-rebinding SSRF defence in web_fetch (resolve-and-validate every address, every redirect hop).
  • Model + web egress redaction and audit at the chokepoints; session and audit-log files created at mode 0600.

Opt-in cloud models

  • Off by default behind [model] allow_cloud. A per-session consent gate states plainly what leaves the device; fail-closed on non-TTY and when allow_cloud is off — no egress without explicit consent.
  • An unmistakable active-cloud indicator (amber ☁ CLOUD status bar + amber model name + /status locality), harness-rendered and unspoofable; cloud_consent_granted and model_request audit events.

Approvals & control

  • Reject-and-steer: approval prompts are [y]es / [e]dit / [n]o. [e] drops the proposed action without running it and feeds your instruction back to the model, which re-proposes a corrected action through the full classify→decide→approve gate. High-risk commands still require typing the literal run.
  • The path shown at the approval gate is the resolved action path, so a model can't spoof an approval with a misleading argument.

Workflow skills

Four opt-in builtins via progressive disclosure (skill_read): debugging, verification, code-review, git-workflow.

UI / UX

  • Redesigned boot banner (sectioned layout, commands + tips + workflow-skills + recent-sessions); streamlined one-key model picker.
  • Persistent status bar pinned at the input: dir · model · profile · locality + ctx%.
  • Approval diffs reveal with a bounded scrolling animation; changed lines render as full-width red/green bars; long diffs window with a … (+N more) footer.
  • !<cmd> one-shot manual-shell escape; /config edit writes a commented starter config.toml when none exists.

Validation

Phase gate green (ruff + ruff format + mypy --strict + 1157 tests); CI green on Python 3.11 and 3.14.

Next: v0.10.1 — a full-screen TUI input dock (framed input box, queueable input, completion-menu integration).

ShellPilot v0.9.0 — skill progressive disclosure

Choose a tag to compare

@lavindeep lavindeep released this 20 Jun 17:47
aa03e29

Skill progressive disclosure

ShellPilot v0.9.0 lets the local model read a skill's deeper documentation on demand rather than force-injecting it into every prompt or leaving it unreachable. The change is additive and opt-in-gated — a default session behaves exactly as it did in v0.8.2.

Highlights

  • skill_read(skill, resource) tool — opens an in-memory skill document by name, scoped to a skill. It never interprets a filesystem path, and invalid or reserved skills are unreadable. Read-only, no approval gate.
  • On-demand resources — any skill resource without a trigger (every template, and every reference outside the planning skill) is now discoverable and readable without being injected. No data-model or loader change was needed.
  • Readable docs menu — when at least one skill is enabled, active skills advertise their on-demand document names in a single compact line, so the model knows what it can open.
  • Opt-in gating — both skill_read and the menu appear only when [skills] enabled is non-empty, mirroring how the web tools register only when web is enabled. A default session gains no new tool surface and no menu.
  • Showcase — the built-in skill-authoring skill's references are now real authoring docs (anatomy, trigger choice, resource routing), and its SKILL.md demonstrates the pattern: a lean injected body that routes to named on-demand docs.
  • README — rewritten from the ground up for the milestone, with an architecture diagram, capability tables, an annotated session, and platform support notes.

Validation

  • Full check suite green (ruff, ruff format --check, mypy --strict, pytest) — 908 tests, on Python 3.11 and 3.14.
  • Live acceptance on gemma4:e4b: the model autonomously read the relevant on-demand docs when the task called for them, and ignored the menu for unrelated work. Cross-model validation on qwen3.5:4b-mlx is deferred.

Notes

  • Planning references remain injected; nothing previously injected moved to on-demand.
  • docs/DESIGN.md (sections 23.1 and 23.4) documents the mechanism.

Full changelog: v0.8.2...v0.9.0

v0.8.2 — Planner hardening (single end-of-plan summary)

Choose a tag to compare

@lavindeep lavindeep released this 20 Jun 15:07
901e3e3

v0.8.2 — Planner hardening (single end-of-plan summary)

A multi-step plan could emit its end-of-plan summary 2–3 times. This release fixes that deterministically, plus related plan-execution hardening.

Fixed

  • Single end-of-plan summary. Once the model explicitly completes the last step (via update_plan) and its reply already contains a substantive summary, the harness ends the turn instead of re-prompting — a finished plan emits one summary, not a repeat. Completion is always explicit (never inferred from prose), so no work is ever skipped. Reproduced on a large cloud model too, so the cause was harness-structural, not small-model flakiness.
  • Idempotent propose_plan. A duplicate identical proposal is now a no-op that continues execution, instead of cancelling the just-approved plan and re-prompting for approval.

Changed

  • Action-only planning guidance — concrete, checkable steps and no dedicated "summarize" step (the summary is automatic), making execution more predictable across models. The stall-recovery nudge is kept and narrowed.
  • Dynamic summary length — scales to the task (brief for simple work, fuller for substantive findings).

Validated live on gemma4:e4b and qwen3.5:4b-mlx: one summary per finished plan, every tool step executed, and the idempotent-propose fix fired under a real double-propose.

v0.8.1 — Web-grounding hardening

Choose a tag to compare

@lavindeep lavindeep released this 15 Jun 10:01

ShellPilot v0.8.1 — Web-grounding hardening

Two standing rules added to the built-in web-grounding skill, motivated by live measurement on small local models:

  • Fetch-recovery. Fetch only URLs that appeared in search results, and on a blocked or failed fetch (e.g. 403/404) re-search for another authoritative source instead of guessing a URL.
  • Current-generation verification. Don't trust the version or product name in the question as current — confirm the current generation from the fetched source.

No backend or provider change (DuckDuckGo remains the zero-config default; SearXNG support is planned for v0.8.5). No runtime, config, or context-window change.

The gemma4:e4b baseline was already robust on the URL-invention / no-recovery axes — this release reinforces that behavior (and hardens weaker models) and nudges against the one residual: going stale when blocked off the official source. Validated live on gemma4:e4b; CI green on Python 3.11 and 3.14 (876 tests).

v0.8.0 — Web-grounding quality

Choose a tag to compare

@lavindeep lavindeep released this 14 Jun 19:01

ShellPilot v0.8.0 — Web-grounding quality for small local models

This release helps a small local model (default gemma4:e4b) verify web claims from sources instead of guessing from search snippets — entirely through deterministic harness guidance, with no backend change.

What changed

  • web-grounding skill — standing grounding guidance. Treat search snippets as leads, not evidence: fetch the official source with web_fetch before asserting a factual, current, or numeric claim. Decompose multi-entity or comparison questions into separate searches. Discover-first query shaping (lead with authority terms like official / documentation / latest release; prefer a specific page over a homepage). Cite sources.
  • Provider-neutral web_search description with a web_fetch bridge. The tool no longer names a specific search engine; it frames results as leads and points the model to web_fetch on the most authoritative result to ground an answer.
  • Actionable web_fetch truncation marker. When a page is capped, the marker now suggests fetching a more specific source instead of guessing from a partial page. The fetch character limit is unchanged.

Not in this release

No provider/backend change — DuckDuckGo remains the keyless, zero-config default. A configurable privacy-first search provider (self-hosted SearXNG behind a seam) is planned for v0.8.5.

Validation

Verified live on gemma4:e4b: bare prompts now search, fetch the official source, and cite it unprompted, and decompose multi-entity comparisons into per-entity searches. 876 tests; CI green on Python 3.11 and 3.14.

v0.7.1 — Instant high-risk approvals

Choose a tag to compare

@lavindeep lavindeep released this 14 Jun 12:35

v0.7.1 — Instant high-risk approvals

High-risk command approvals now appear instantly. The risk-purpose explanation shown before a dangerous command is generated deterministically from the policy classifier's reasons, instead of via a separate blocking model call. That removed a per-command LLM round-trip — and its context-window reconfigure — that could stall the approval prompt for minutes on small local models (the rm was always instant; the wait was the model narrating).

No change to safety behavior — risk classification, the approval decision, and the typed-run gate are untouched. Only how the explanation text is produced changed. Sensitive-file reads still show no purpose line, exactly as before.

  • New deterministic explain_risk in the policy layer, with a sentence for every classifier reason (kept honest by a drift-guard test).
  • Removed the LLM explainer plumbing (EXPLAINER_PROMPT, the _explain_purpose round-trip, and the injection seam) — the last blocking per-command model call.
  • 874 tests; CI green on Python 3.11 and 3.14.

v0.7.0 — Skills v2

Choose a tag to compare

@lavindeep lavindeep released this 13 Jun 18:11

Skills v2 — trigger-driven skill assembly tuned for small local models. Instead of exposing skills as model-facing tools, ShellPilot's harness deterministically injects only the guidance relevant to the current runtime state, keeping a 4B model focused.

Highlights

  • Crisp deterministic triggersALWAYS_ON, ENABLED, PLAN_PROPOSED, PLAN_ACTIVE, PLAN_BLOCKED, WEB_ENABLED. No intent inference; every trigger has an exact predicate.
  • Four builtin skills:
    • planning — proposal/active/blocked mode references; the harness shows only the rule for the current plan phase.
    • context-management — always-on, tiny operating rules for file triage and context budgeting.
    • web-grounding — active only when web tools are actually registered.
    • skill-authoring — opt-in via [skills] enabled.
  • Read-only resources — skills may bundle references/ and templates/; the relevant reference is selected by the harness.
  • Script discovery (not execution)scripts/manifest.json is discovered and validated for visibility, but execution is deferred to v0.8.0 with its own safety design. No skill code runs in this release.
  • Enriched inspection/skills shows triggers, resources, status, active state, and reasons; /context shows per-block token estimates, injection state, and skip reasons.
  • Slimmer base prompt (PROMPT_VERSION 4) — proposal-time discipline stays in the base prompt; execution and blocker discipline live in the planning skill.

Notes

  • [skills] enabled is config-file only (no env var, no /config set, no overrides).
  • Skill resource discovery is path-safety hardened (rejects traversal/absolute/symlink escapes) and bounded (per-file and per-folder caps) so a stray skill folder can't read outside its root or stall startup.
  • Reserved builtin names cannot be shadowed by user skills.

Deferred (on record)

  • Skill script execution → v0.8.0 (controlled runner + approval/precheck integration).
  • Intent-inference triggers (debugging/verification/brainstorming) and richer workflow skills → v0.9.0 candidates.

Validated live on gemma4:e4b. Full test suite (832) and CI green on Python 3.11 and 3.14.