From 489cffcb69e9a205b58044d9a673b8be31139b07 Mon Sep 17 00:00:00 2001 From: K1-R1 <77465250+K1-R1@users.noreply.github.com> Date: Tue, 17 Mar 2026 04:04:14 +0000 Subject: [PATCH 1/4] docs: fix stale test count and version example in README MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - FAQ: 228 tests → 231 (3 new tests added in v1.0.2) - Install env vars table: example version 1.0.1 → 1.0.2 Signed-off-by: K1-R1 <77465250+K1-R1@users.noreply.github.com> --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8c5ebe1..efdae4d 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,7 @@ The installer supports these environment variables: | Variable | Default | Description | | --- | --- | --- | | `SMOOSH_INSTALL_DIR` | `/usr/local/bin` | Installation directory | -| `SMOOSH_VERSION` | latest | Pin a specific version (e.g. `1.0.1`) | +| `SMOOSH_VERSION` | latest | Pin a specific version (e.g. `1.0.2`) | | `SMOOSH_NO_CONFIRM` | `0` | Set to `1` to skip confirmation prompt | | `SMOOSH_NO_VERIFY` | `0` | Set to `1` to skip checksum verification (unsafe) | @@ -386,7 +386,7 @@ smoosh counts words using `wc -w`, which splits on whitespace. Code files with dense syntax (JSON, minified JS) count differently than prose. **Is it overengineered for a shell script?** -Absolutely. 228 tests, 100% file inclusion verification, CDATA escaping for +Absolutely. 231 tests, 100% file inclusion verification, CDATA escaping for XML output, and a box-drawing letter logo. But your codebase deserves to be smooshed properly. From 97740531a1bcba9453172bd316d07d855d790e6d Mon Sep 17 00:00:00 2001 From: K1-R1 <77465250+K1-R1@users.noreply.github.com> Date: Tue, 17 Mar 2026 04:41:41 +0000 Subject: [PATCH 2/4] docs: tighten README and CONTRIBUTING prose MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Cut generic "AI tools are powerful" opener in Why smoosh — start with the specific pain point - Remove abstract "Technical knowledge becomes accessible" sentence and its negative parallelism ("not just X") - Replace "No hallucinations, all sources cited" overclaim with factual "all with source citations" - Remove chatbot opener from CONTRIBUTING.md Signed-off-by: K1-R1 <77465250+K1-R1@users.noreply.github.com> --- CONTRIBUTING.md | 2 -- README.md | 15 ++++++--------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f8c232e..01c14cb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,7 +1,5 @@ # Contributing to smoosh -Thank you for your interest in contributing! - ## Prerequisites - Bash 3.2+ (test with `bash --version`) diff --git a/README.md b/README.md index efdae4d..0e6335f 100644 --- a/README.md +++ b/README.md @@ -35,16 +35,13 @@ drop into your AI tool of choice. ## Why smoosh? -AI tools are powerful when they have the right context. The hard part is -getting an entire codebase into them — in the right format, within token -limits, without accidentally including secrets. smoosh handles all of that -in one command. +Getting an entire codebase into an AI tool — right format, within token +limits, no secrets — is the tedious part. smoosh does it in one command. **Understand your codebase in plain language.** Upload smoosh output to NotebookLM and ask questions about architecture, module boundaries, or what -that obscure utility actually does. Technical knowledge becomes accessible to -everyone on the team — not just the people who wrote the code. Product, -design, and leadership get answers without reading source files. +that obscure utility actually does. Product, design, and leadership get +answers without reading source files. **Give AI real context.** Drop the output into Claude Projects or ChatGPT and get an assistant that actually knows your codebase. No @@ -237,8 +234,8 @@ smoosh --code **Step 4 — Chat with your codebase** -Ask about architecture, find functions, generate onboarding guides, or get -plain-English explanations of complex modules. No hallucinations, all sources cited. +Ask about architecture, find functions, or get plain-English explanations +of complex modules — all with source citations. **NotebookLM limits (as of early 2026):** From b4f610b019ce395548098c11abf658902330e52a Mon Sep 17 00:00:00 2001 From: K1-R1 <77465250+K1-R1@users.noreply.github.com> Date: Tue, 17 Mar 2026 04:57:08 +0000 Subject: [PATCH 3/4] chore: remove internal artefacts from tracking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove docs/plans/ plan file that was committed despite docs/ gitignore (git rm --cached — gitignore only prevents untracked files) - Remove .agent/ directory (redundant with CLAUDE.md and CONTRIBUTING.md) - Add .agent/ to .gitignore Local copies preserved. No content changes. Signed-off-by: K1-R1 <77465250+K1-R1@users.noreply.github.com> --- .agent/rules/smoosh.md | 25 -- .agent/workflows/build-and-test.md | 39 --- .gitignore | 3 + ...7-001-fix-acceptance-test-findings-plan.md | 248 ------------------ 4 files changed, 3 insertions(+), 312 deletions(-) delete mode 100644 .agent/rules/smoosh.md delete mode 100644 .agent/workflows/build-and-test.md delete mode 100644 docs/plans/2026-03-17-001-fix-acceptance-test-findings-plan.md diff --git a/.agent/rules/smoosh.md b/.agent/rules/smoosh.md deleted file mode 100644 index 6f29d95..0000000 --- a/.agent/rules/smoosh.md +++ /dev/null @@ -1,25 +0,0 @@ -# smoosh - -Pure bash CLI tool. Zero external dependencies beyond git and standard POSIX tools. - -## Constraints - -- Bash 3.2 compatible (macOS ships 3.2). No associative arrays, no mapfile, no `${var,,}`, no named references. -- Single file (`smoosh`). No sourced libraries. Everything in one script. -- 2-space indentation. Functions <= 100 lines. -- All warnings from shellcheck must be resolved. -- Never use `echo "$var"` for filenames — use `printf '%s\n' "$var"`. -- Never use `sed -i` — write to temp file, then `mv`. -- Always use `--` before file arguments in commands. -- All non-content output goes to stderr. - -## Testing - -- Framework: bats-core with bats-assert and bats-support -- Fixtures in `test/fixtures/` — small git repos for each test scenario -- Every feature must have tests. Every edge case must have tests. - -## Commits - -- Use conventional commits: `feat:`, `fix:`, `test:`, `docs:`, `chore:`, `refactor:`. -- Sign every commit with `-s` (DCO requirement): `git commit -s`. diff --git a/.agent/workflows/build-and-test.md b/.agent/workflows/build-and-test.md deleted file mode 100644 index bad0d5b..0000000 --- a/.agent/workflows/build-and-test.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -description: Run the project's build, test, and formatting checks ---- - -# Build and Test Workflow - -Use this workflow to run all tests, formatters, and linters for the `smoosh` project. - -// turbo-all - -1. Run pre-commit checks (lint, format, spelling): - - ```bash - prek run - ``` - -2. Run all tests: - - ```bash - bats test/*.bats - ``` - -3. Lint the bash script: - - ```bash - shellcheck smoosh - ``` - -4. Format check the bash script: - - ```bash - shfmt -d -i 2 smoosh - ``` - -5. Verify usage output: - - ```bash - ./smoosh --help - ``` diff --git a/.gitignore b/.gitignore index 1480bb3..3b9ec5c 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,9 @@ _smooshes/ # Claude Code local settings (not for public consumption) .claude/settings.local.json +# agent config (redundant with CLAUDE.md and CONTRIBUTING.md) +.agent/ + # internal planning artefacts (not for public consumption) docs/ todos/ diff --git a/docs/plans/2026-03-17-001-fix-acceptance-test-findings-plan.md b/docs/plans/2026-03-17-001-fix-acceptance-test-findings-plan.md deleted file mode 100644 index cc0cc86..0000000 --- a/docs/plans/2026-03-17-001-fix-acceptance-test-findings-plan.md +++ /dev/null @@ -1,248 +0,0 @@ ---- -title: "fix: Resolve acceptance test findings" -type: fix -status: completed -date: 2026-03-17 ---- - -# fix: Resolve acceptance test findings - -## Overview - -Acceptance testing (human walkthrough + agent walkthrough) surfaced 2 bugs, -security hardening items, and documentation gaps. A follow-up audit expanded the -raw findings to ~25. This plan resolves all actionable findings to best practices -before promotional activity begins. - -## Triage - -Each dismissed finding was re-evaluated with justification: - -**Excluded (with rationale):** - -| Finding | Verdict | Justification | -|---------|---------|---------------| -| `--output-dir` path traversal | Dismissed | User controls all inputs on a local CLI tool. Rejecting `..` would break legitimate `--output-dir ../shared-output`. No privilege boundary crossed. | -| `mktemp` explicit error handling | Dismissed | `set -euo pipefail` (line 6) already propagates `mktemp` failures from `$()` substitution. Adding `\|\| die` to 8 callsites is redundant. | -| Remote clone symlink race condition | Dismissed | Two-pass remove+verify is sound. The "race" requires attacker write access to a `mktemp -d` dir — meaning they already have the user's UID. | -| `sed` injection in release.yml | Dismissed | `tarball_url` comes from `github.ref_name` (git tags can't contain `&` or `\`). `sha256` is hex from `sha256sum`. Neither can contain sed specials. | -| Token in git clone URL | Dismissed | Standard cross-repo GH Actions pattern. Fine-grained PAT, scoped to one repo. GitHub auto-masks secrets in logs. | -| Pre-release binary validation | Dismissed | smoosh is a bash script. Suggested `file \| grep ELF` check would actually fail. SHA256 checksum IS the integrity check. | -| Troubleshooting section | Dismissed | No user reports yet. Shadow binary issue covered by uninstall section (D2). Add when real issues arrive. | -| `LC_ALL=C` documentation | Dismissed | Set internally by smoosh for consistent sorting. Not consumed from user's environment. Documenting it would confuse. | - -**Included:** everything below. - -## Bugs - -### B1. `.gitignore` write crashes on read-only repos - -- **File:** `smoosh:710-745` -- **Symptom:** When an agent uses `--output-dir /external/path` on a local repo - it has read-only access to, `mktemp` in `REPO_ROOT` fails with exit 1. -- **Root cause:** Line 710-711 warns when output-dir is outside the repo, but - execution falls through to line 733 which creates a temp file in REPO_ROOT. - The `.gitignore` entry would be meaningless anyway — it would contain an - absolute external path. -- **Fix:** After the "outside repo" warning on line 711, add `return 0`. -- **Test:** New bats test — run smoosh with `--output-dir` pointing outside the - repo fixture. Assert success. Assert `.gitignore` in the repo is unchanged. - (Existing test `smoosh_edge_cases.bats:251` asserts only the warning message; - it doesn't verify that `.gitignore` is left untouched.) - -### B2. README curl install pinned to v1.0.0 - -- **File:** `README.md:97,104` -- **Symptom:** New users following README install v1.0.0 instead of latest. -- **Fix:** Change from tag-pinned URL to `main` branch: - ``` - https://raw.githubusercontent.com/K1-R1/smoosh/main/install.sh - ``` - The install.sh script already resolves the latest release version at runtime - via GitHub API — the tag in the URL only controls which version of - `install.sh` itself is fetched, not which smoosh version is installed. - Using `main` means users always get the latest install script. -- **Test:** Not testable in bats (documentation). - -### B2b. install.sh header comment pinned to v1.0.0 - -- **File:** `install.sh:5` -- **Fix:** Update to match README (use `main`). -- **Test:** Not testable in bats (documentation comment). - -## Security hardening - -### S1. `.gitignore` symlink check - -- **File:** `smoosh:722-743` -- **Issue:** `.gitignore` modification doesn't verify it's a regular file. If - `.gitignore` is a symlink, the `cp` + `mv` pattern would overwrite the - symlink target. -- **Fix:** Add before line 730: - ```bash - if [[ -L "${gitignore}" ]]; then - warn ".gitignore is a symlink — skipping auto-update" - return 0 - fi - ``` -- **Test:** New bats test — create a repo fixture with `.gitignore` as a - symlink to another file. Run smoosh. Assert the symlink target is unchanged. - Assert warning message is emitted. - -### S2. README manual install lacks checksum verification - -- **File:** `README.md:109-113` -- **Issue:** Manual install downloads binary without integrity check. The - `install.sh` path has SHA256 verification, but the "manual" shortcut bypasses - it entirely. -- **Fix:** Add checksum step to the manual install instructions: - ```bash - curl -fsSL https://github.com/K1-R1/smoosh/releases/latest/download/smoosh -o smoosh - curl -fsSL https://github.com/K1-R1/smoosh/releases/latest/download/smoosh.sha256 -o smoosh.sha256 - sha256sum -c smoosh.sha256 - chmod +x smoosh - sudo mv smoosh /usr/local/bin/ - ``` -- **Test:** Not testable in bats (documentation). - -### S3. release.yml uses /tmp instead of $RUNNER_TEMP - -- **File:** `.github/workflows/release.yml:126,132` -- **Issue:** Files written to world-readable `/tmp`. GitHub provides - `$RUNNER_TEMP` as a per-job temp directory. -- **Fix:** Replace `/tmp/smoosh-src.tar.gz` with `"$RUNNER_TEMP/smoosh-src.tar.gz"` - and `/tmp/homebrew-tap` with `"$RUNNER_TEMP/homebrew-tap"`. -- **Test:** Not testable in bats (CI workflow). - -### S4. install.sh sudo escalation without notice - -- **File:** `install.sh:158-166` -- **Issue:** Script tries `install -m 755` silently, then falls back to `sudo` - without notice. On systems with NOPASSWD sudo, this escalates without any - user-visible indication. In the `curl | bash` context, the user can't inspect - what happens before execution. -- **Fix:** Add `warn` before the sudo fallback: - ```bash - if install -m 755 "${tmp_bin}" "${INSTALL_DIR}/${BINARY_NAME}" 2>/dev/null; then - : # success without sudo - else - warn "Writing to ${INSTALL_DIR} requires elevated privileges (sudo)." - if sudo install -m 755 "${tmp_bin}" "${INSTALL_DIR}/${BINARY_NAME}"; then - : # success with sudo - else - die "Installation failed. Try: SMOOSH_INSTALL_DIR=\$HOME/.local/bin bash install.sh" - fi - fi - ``` -- **Test:** Not deterministically testable without mocking filesystem - permissions. The fix is a single `warn` line — low risk, no test needed. - -## Documentation improvements - -### D1. Add table of contents to README - -- **File:** `README.md` (top, after logo/tagline) -- **Content:** Linked section headings for Quick Start, Why smoosh, Features, - Installation, Usage, AI Tools, Config Reference, FAQ, Contributing, Licence. - -### D2. Add uninstall instructions - -- **File:** `README.md` (new section after Installation) -- **Content:** - - Homebrew: `brew uninstall smoosh` - - curl/manual: `rm /usr/local/bin/smoosh` (or `which smoosh` to find it) - - Note: if you installed via both methods, check `which smoosh` after removing - one — a shadow binary may remain. - -### D3. Add `--no-color` to README config reference - -- **File:** `README.md:247-267` -- **Issue:** Flag exists in `--help` and code but missing from README table. -- **Fix:** Add row: `--no-color | — | Disable colour output` - -### D4. Document colour environment variables - -- **File:** `README.md` (in or near config reference) -- **Content:** Precedence: `--no-color` flag > `NO_COLOR` > `FORCE_COLOR` > - `CLICOLOR` > TTY auto-detect. Link to https://no-color.org/. - -### D5. Add agent/CI usage section - -- **File:** `README.md` (expand "Using smoosh with AI tools" or new subsection) -- **Content:** - - Recommended agent pre-flight: `smoosh --json --dry-run --all .` - - Recommended agent execution: `smoosh --no-interactive --json --all .` - - JSON output schema example (show actual structure from dry-run) - - Exit codes for programmatic decision-making - - Note: `--json` goes to stdout, status to stderr — safe to pipe - -### D6. Add agent example to `--help` - -- **File:** `smoosh` (help text, Examples section) -- **Add:** - ``` - smoosh --no-interactive --json . # agent / CI pipeline - ``` -- **Test:** Assert `--help` output contains `--no-interactive --json`. - -### D7. Document install.sh env vars in README - -- **File:** `README.md` (near curl install section) -- **Content:** Brief mention of `SMOOSH_VERSION`, `SMOOSH_INSTALL_DIR`, - `SMOOSH_NO_CONFIRM`, `SMOOSH_NO_VERIFY` with one-line descriptions. - -## New tests summary - -| Test | File | What it asserts | -|------|------|-----------------| -| External output-dir skips .gitignore | `smoosh_edge_cases.bats` | `--output-dir /tmp/ext` succeeds; repo `.gitignore` unchanged | -| Symlink .gitignore skipped with warning | `smoosh_edge_cases.bats` | `.gitignore` symlink target unchanged; warning emitted | -| `--help` includes agent example | `smoosh_args.bats` | Output contains `--no-interactive --json` | - -## Implementation phases - -### Phase 1: Bug fixes + security hardening (smoosh script) - -1. Fix B1 — add early return in `ensure_output_dir` when output is outside repo -2. Fix S1 — add symlink check before `.gitignore` modification -3. Fix S4 — add sudo warning in install.sh -4. Add agent example to `--help` (D6) -5. Write 3 new bats tests -6. Run: `shellcheck smoosh && shfmt -d -i 2 smoosh && bats test/*.bats` - -### Phase 2: Version pinning + CI fixes - -7. Fix B2 — update README curl URLs from `v1.0.0` to `main` -8. Fix B2b — update install.sh header comment -9. Fix S2 — add checksum verification to README manual install -10. Fix S3 — use `$RUNNER_TEMP` in release.yml - -### Phase 3: README documentation - -11. Add table of contents (D1) -12. Add uninstall section (D2) -13. Add `--no-color` to config reference (D3) -14. Document colour env vars (D4) -15. Add agent/CI usage section with JSON schema example (D5) -16. Document install.sh env vars (D7) - -### Phase 4: Verify - -17. `shellcheck smoosh` -18. `shfmt -d -i 2 smoosh` -19. `bats test/*.bats` -20. `prek run` - -## Acceptance criteria - -- [x] `smoosh --output-dir /tmp/ext --no-interactive .` succeeds on a repo - without crashing (B1 fix + test) -- [x] `.gitignore` symlink is not followed (S1 fix + test) -- [x] `--help` output contains agent example (D6 + test) -- [x] README curl install references `main` branch, not a version tag -- [x] README manual install includes SHA256 verification step -- [x] install.sh warns before sudo escalation -- [x] release.yml uses `$RUNNER_TEMP` -- [x] README has table of contents, uninstall section, `--no-color` in config - table, colour env vars, agent usage section, install.sh env vars -- [x] All checks pass: shellcheck, shfmt, bats, prek From 83c282d32bbc5ecfb8f997af0f1d1098fd1712b9 Mon Sep 17 00:00:00 2001 From: K1-R1 <77465250+K1-R1@users.noreply.github.com> Date: Tue, 17 Mar 2026 04:59:54 +0000 Subject: [PATCH 4/4] chore: restore .agent/ to tracking Agent rules and workflows are useful for contributors using AI tools other than Claude Code (Codex, Gemini CLI, etc.). Signed-off-by: K1-R1 <77465250+K1-R1@users.noreply.github.com> --- .agent/rules/smoosh.md | 25 +++++++++++++++++++ .agent/workflows/build-and-test.md | 39 ++++++++++++++++++++++++++++++ .gitignore | 3 --- 3 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 .agent/rules/smoosh.md create mode 100644 .agent/workflows/build-and-test.md diff --git a/.agent/rules/smoosh.md b/.agent/rules/smoosh.md new file mode 100644 index 0000000..6f29d95 --- /dev/null +++ b/.agent/rules/smoosh.md @@ -0,0 +1,25 @@ +# smoosh + +Pure bash CLI tool. Zero external dependencies beyond git and standard POSIX tools. + +## Constraints + +- Bash 3.2 compatible (macOS ships 3.2). No associative arrays, no mapfile, no `${var,,}`, no named references. +- Single file (`smoosh`). No sourced libraries. Everything in one script. +- 2-space indentation. Functions <= 100 lines. +- All warnings from shellcheck must be resolved. +- Never use `echo "$var"` for filenames — use `printf '%s\n' "$var"`. +- Never use `sed -i` — write to temp file, then `mv`. +- Always use `--` before file arguments in commands. +- All non-content output goes to stderr. + +## Testing + +- Framework: bats-core with bats-assert and bats-support +- Fixtures in `test/fixtures/` — small git repos for each test scenario +- Every feature must have tests. Every edge case must have tests. + +## Commits + +- Use conventional commits: `feat:`, `fix:`, `test:`, `docs:`, `chore:`, `refactor:`. +- Sign every commit with `-s` (DCO requirement): `git commit -s`. diff --git a/.agent/workflows/build-and-test.md b/.agent/workflows/build-and-test.md new file mode 100644 index 0000000..bad0d5b --- /dev/null +++ b/.agent/workflows/build-and-test.md @@ -0,0 +1,39 @@ +--- +description: Run the project's build, test, and formatting checks +--- + +# Build and Test Workflow + +Use this workflow to run all tests, formatters, and linters for the `smoosh` project. + +// turbo-all + +1. Run pre-commit checks (lint, format, spelling): + + ```bash + prek run + ``` + +2. Run all tests: + + ```bash + bats test/*.bats + ``` + +3. Lint the bash script: + + ```bash + shellcheck smoosh + ``` + +4. Format check the bash script: + + ```bash + shfmt -d -i 2 smoosh + ``` + +5. Verify usage output: + + ```bash + ./smoosh --help + ``` diff --git a/.gitignore b/.gitignore index 3b9ec5c..1480bb3 100644 --- a/.gitignore +++ b/.gitignore @@ -21,9 +21,6 @@ _smooshes/ # Claude Code local settings (not for public consumption) .claude/settings.local.json -# agent config (redundant with CLAUDE.md and CONTRIBUTING.md) -.agent/ - # internal planning artefacts (not for public consumption) docs/ todos/