Releases: dotcommander/shoop
Releases · dotcommander/shoop
v0.3.3 — security hardening + review fixes
What's changed
Post-review hardening pass on top of v0.3.2's prompt optimization work.
Security
web_fetchSSRF defense: reject URLs targeting loopback (127.*,::1,localhost), link-local metadata (169.254.*including cloud-metadata169.254.169.254), and RFC1918 private ranges (10.*,192.168.*,172.16–31.*,fc*/fd*). Reduced--max-redirsfrom 5 → 3 (note: defense is best-effort — curl does not re-validate redirect targets).
Bug fixes
call_api: replaced globally-scopedRETURNtrap with explicitrm -f "$auth_file"after curl. The trap was firing on every subsequent function return across the script, stomping$auth_filestate.- Typo detector false-positives: tightened from the previous same-first-3/±2-char heuristic to strict prefix truncation only. Words like
helper,held,configureno longer get rejected with "did you mean 'help'?".sess→sessions,hel→help, and other genuine truncations still work. manage_context: switched summary-input cap fromhead -c 8000(byte-based, could split a multi-byte UTF-8 rune) tohead -n 200(line-based, UTF-8 safe).
Code quality
is_binary: simplified fragile$(...) && [[ ]] && return 0 || truechain into direct[[ ]] && return 0checks.read_file: dropped dead|| echo 0guards onwc -landgrep -c ''(never triggered).resume: removed redundant${SESSION_ID%%--*}double-strip.run_format_hook: documentedFORMAT_CMDtrust boundary (user-owned, chmod 600 config).
Version bump: SHOOP_VERSION → 0.3.3
v0.3.2 content (not separately released, folded here):
- Optimized system prompt, CRISP rewriter, and context summarizer with truncation awareness, denial handling, and error recovery guidance.
v0.3.1 — refactor + UX fixes + bug fixes
What's changed
Refactoring (8 function extractions)
run_with_timeout— wraps timeout-safe command executionsafe_write— TOCTOU-safe atomic file writes (extracted fromwrite_fileandreplace_in_file)trim_messages— hard window fallback for context managementdie_ambiguous_sessions— prints matching sessions and exitsfind_session— locate session by exact/substring/content searchmanage_context— LLM summarization with hard-trim fallback (replaces inline sliding window)dispatch_tool— all tool implementations in one function (agent loop: 300 → ~80 LOC)- Nullglob subshell cleanup throughout session/subcommand code
UX improvements
- Typo guard: bare lowercase words resembling known commands print "did you mean?" hint
- Config migration: appends missing
REWRITE/FORMAT_CMD/CHECKPOINTkeys to older config files - TTY guard fix:
confirm_or_skipnow usestrue </dev/ttyopenability test instead of-e /dev/tty config showsubcommand prints config with API key redacted- Session list displays deduplicated timestamp IDs in fixed-width columns
resumeshows last assistant message preview before prompting for continuation
Bug fixes
find_sessionwas defined after its call site — moved before thecasesubcommand block- Session resume double-slug:
SESSION_IDcontained the slug;save_sessionwas appending it again — fixed by splitting on--at resume time run_format_hookwas placed insidesafe_writewhere its appended output got overwritten by the outer result assignment — moved to call sites inwrite_fileandreplace_in_fileweb_fetchtool display:_tdispnow includes.urlin the jq selector
Version bump: SHOOP_VERSION set to 0.3.1
v0.3.0
Full Changelog: v0.2.0...v0.3.0
v0.2.0 — Tool improvements, DRY refactors, and security hardening
What's new
Tool improvements
- read_file: line range support (
start_line/end_line) and binary file detection - search_files:
context_linesandcase_insensitiveparameters - run_shell:
timeoutparameter (1–300s, default 30); requires interactive terminal - list_dir: new tool to browse directory trees (no confirmation needed)
- Truncation: smart head+tail strategy — shows first and last N/4 lines instead of cutting at the top
DRY refactors
reject_toolandconfirm_or_skiphelpers eliminate repeated inline patterns- Batched
jq+@tsvreads reduce jq fork count per turn mapfile-based truncation replaces fragilewc -l+printfchainjq -npayloads for API calls;call_apinow receives payload as argument
Security hardening
- Working directory confinement:
check_path/resolve_pathblock traversal outside$WORKDIR - Config loaded safely with
while IFS='=' read— neversource; config dir/file get 700/600 perms - API key passed via temp file with
trap RETURNcleanup — never interpolated into command strings - Session IDs validated against
^[0-9]{8}-[0-9]{6}-[0-9]+$before use run_shellalways requires confirmation regardless of--no-confirm/CONFIRM=0