RepoPilotOpen in app →

bitfield/script

Making it easy to write shell-like scripts in Go

Healthy

Healthy across all four use cases

weakest axis
Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 8mo ago
  • 14 active contributors
  • MIT licensed
Show all 7 evidence items →
  • CI configured
  • Tests present
  • Slowing — last commit 8mo ago
  • Concentrated ownership — top contributor handles 79% of recent commits

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/bitfield/script)](https://repopilot.app/r/bitfield/script)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/bitfield/script on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: bitfield/script

Generated by RepoPilot · 2026-05-09 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/bitfield/script shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across all four use cases

  • Last commit 8mo ago
  • 14 active contributors
  • MIT licensed
  • CI configured
  • Tests present
  • ⚠ Slowing — last commit 8mo ago
  • ⚠ Concentrated ownership — top contributor handles 79% of recent commits

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live bitfield/script repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/bitfield/script.

What it runs against: a local clone of bitfield/script — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in bitfield/script | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch master exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 263 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>bitfield/script</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of bitfield/script. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/bitfield/script.git
#   cd script
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of bitfield/script and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "bitfield/script(\\.git)?\\b" \\
  && ok "origin remote is bitfield/script" \\
  || miss "origin remote is not bitfield/script (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT at generation time"

# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
  && ok "default branch master exists" \\
  || miss "default branch master no longer exists"

# 4. Critical files exist
test -f "script.go" \\
  && ok "script.go" \\
  || miss "missing critical file: script.go"
test -f "doc.go" \\
  && ok "doc.go" \\
  || miss "missing critical file: doc.go"
test -f "go.mod" \\
  && ok "go.mod" \\
  || miss "missing critical file: go.mod"
test -f "script_test.go" \\
  && ok "script_test.go" \\
  || miss "missing critical file: script_test.go"
test -f "README.md" \\
  && ok "README.md" \\
  || miss "missing critical file: README.md"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 263 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~233d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/bitfield/script"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

script is a Go library that brings shell script ergonomics to Go programs, enabling pipelines of operations on data streams (files, processes, stdin). It lets you chain operations like File().Match().CountLines() or Stdin().FilterLine().Stdout() with a fluent API inspired by Unix pipes, eliminating boilerplate for common sysadmin and data processing tasks. Simple, focused monolith: script.go is the core engine (~2000 LOC estimated) defining the Pipe type and all chainable methods. script_test.go contains unit tests; platform-specific behavior isolated in script_unix_test.go and script_windows_test.go. Testdata directory holds fixture files (logs, JSON, tar.zip) and txtar integration test scripts. No subdirectories—the entire public API lives in one package.

👥Who it's for

Go developers and DevOps engineers writing system administration tools, CLI utilities, and data processing scripts who want shell-script simplicity without dropping into bash. Users value clean piping syntax over explicit goroutines and channel wrangling.

🌱Maturity & risk

Production-ready and actively maintained. The project has comprehensive test coverage across Unix and Windows variants (script_test.go, script_unix_test.go, script_windows_test.go), dual CI workflows (audit.yml, ci.yml), and depends on stable, widely-trusted libraries (mvdan.cc/sh, itchyny/gojq). Latest activity and lack of major version instability suggest ongoing care.

Very low risk. Dependency footprint is minimal (5 direct deps, all well-maintained) with no recent critical CVEs. Single-maintainer repo (bitfield) is a known quantity in the Go community. No breaking changes visible in go.mod constraints (go 1.18 is reasonable). Primary risk is feature velocity: this is a focused, mature library, so don't expect rapid feature additions—it's stable by design.

Active areas of work

No active development signals visible in file structure (no CHANGELOG, no milestones listed). The library appears to be in a stable maintenance phase—well-tested, documented, and not expecting major features. Contribution focus is likely bug fixes and platform compatibility (note explicit Unix/Windows test split).

🚀Get running

git clone https://github.com/bitfield/script.git
cd script
go mod download
go test ./...

Daily commands: No server/daemon. For dev iteration: go test ./... -v runs full test suite. go test ./... -run TestName runs specific tests. Single-file main.go examples would live outside this library (see README examples for usage patterns).

🗺️Map of the codebase

  • script.go — Core library implementation containing the Pipe type and all chainable methods that form the foundation of the pipeline architecture.
  • doc.go — Package documentation defining the library's purpose, design philosophy, and usage patterns that every contributor must understand.
  • go.mod — Dependency manifest showing critical external packages (gojq, mvdan.cc/sh) that power shell-like operations and query capabilities.
  • script_test.go — Comprehensive test suite establishing expected behavior and serving as executable documentation for all pipeline operations.
  • README.md — Primary entry point explaining library purpose, design rationale, and basic usage patterns for new contributors.
  • .github/workflows/ci.yml — Continuous integration configuration defining test, build, and quality gates that all PRs must pass.

🧩Components & responsibilities

  • Pipe (pipeline orchestrator) (Go io.Reader interface, method chaining pattern) — Maintains internal Reader and error state; chains operations by wrapping Reader and composing transforms; materializes results on terminal call
    • Failure mode: Silently accumulates error in internal state until Error() or String() called; first error stops pipeline but doesn't panic
  • Exec (shell executor) (os/exec, mvdan.cc/sh parser, platform-specific process APIs) — Spawns subprocess, captures stdout, wraps result back into Pipe for further chaining
    • Failure mode: Subprocess errors (exit code != 0) stored in Pipe state; non-zero exit does not stop chaining but will surface in final Error()
  • Filter/Map/JQ (stream transformers) (bufio.Scanner, strings, gojq for JSON) — Read input line-by-line or bulk; apply predicate or transformation; write matching/transformed lines to output Reader
    • Failure mode: Transformation errors (invalid regex, malformed JSON) stop processing and set Pipe error state
  • Test suite (verification) (Go testing.T, google/go-cmp, txtar for shell script definitions) — Validates all operations across Unix/Windows platforms; uses test fixtures from testdata/
    • Failure mode: Failed tests block CI/CD; audit workflow catches security vulnerabilities

🔀Data flow

  • File system (testdata/)Pipe via File() or Exec() — Input data sourced from test fixtures or live file system; read into pipeline as io.Reader
  • Pipe (previous operation output)Pipe (next chained operation) — Each method wraps the previous Reader, composing transforms; data flows line-by-line or bulk through wrapped Readers
  • Pipe internal ReaderString() or Error() — Terminal method reads entire remaining stream and materializes result as string or error
  • Exec subprocessPipe Reader — Subprocess stdout captured and wrapped as io.Reader for downstream operations
  • Filter predicate (regex/lambda)Output Reader — Matching or non-matching lines selected/dropped; gojq expressions evaluate JSON at runtime

🛠️How to make changes

Add a New Pipeline Operation Method

  1. Define the new method on the Pipe receiver in script.go, accepting operation-specific parameters (script.go)
  2. Implement the method to return *Pipe, applying your transformation logic to the internal data stream (script.go)
  3. Add comprehensive test cases in script_test.go covering normal cases, edge cases, and error conditions (script_test.go)
  4. If platform-specific, add OS-specific tests in script_unix_test.go or script_windows_test.go (script_unix_test.go)
  5. Add test fixtures to testdata/ directory if your operation needs sample input files (testdata/)

Add Support for a New Shell Language Feature

  1. Identify the feature and check if mvdan.cc/sh already parses it; if extending shell compatibility, update Exec() in script.go (script.go)
  2. Add test cases in script_test.go demonstrating the new shell syntax working end-to-end (script_test.go)
  3. Add platform-specific tests if shell behavior differs between Unix and Windows (script_unix_test.go)

Add a New Data Transformation Filter

  1. Implement as a new method on Pipe in script.go that reads input and applies line-by-line or bulk transformation logic (script.go)
  2. Leverage existing dependencies (gojq for queries, mvdan.cc/sh for shell patterns) if applicable (script.go)
  3. Add test fixtures in testdata/ (JSON, logs, or text files) representing inputs your filter will process (testdata/)
  4. Write comprehensive tests in script_test.go verifying correctness on various input types (script_test.go)

🔧Why these technologies

  • Go 1.18+ with generics-ready stdlib — Enables cross-platform system scripting with better performance and type safety than shell; method chaining mirrors familiar pipeline syntax
  • mvdan.cc/sh/v3 (shell parser) — Parses and executes shell commands safely within Go process, allowing Exec() to handle complex shell pipelines and syntax
  • itchyny/gojq (JSON query engine) — Provides jq-like JSON filtering and transformation capabilities without subprocess overhead
  • google/go-cmp (diffing library) — Deep comparison for test assertions, making test failures readable and debuggable

⚖️Trade-offs already made

  • Stream-based pipeline architecture rather than loading entire files into memory

    • Why: Allows processing of arbitrarily large files without memory explosion, matching shell script behavior
    • Consequence: Operations must be composable and stateless; cannot easily look-ahead or require random access
  • Embed shell execution via subprocess (Exec) rather than pure Go reimplementation

    • Why: Reuses existing shell semantics and tool ecosystem; simpler than reimplementing shell in Go
    • Consequence: Cross-platform differences require platform-specific test suites; subprocess overhead for very small operations
  • Method chaining (fluent API) for pipeline construction

    • Why: Mirrors familiar shell syntax (cmd | filter | transform) and is intuitive for sequential transformations
    • Consequence: All methods return *Pipe, making it impossible to handle errors mid-pipeline without explicit checking; requires terminal method (.String(), .Error()) to materialize result
  • No explicit buffering or batching layer; lines processed one-at-a-time

    • Why: Simplicity and predictability; easier to reason about memory usage and control flow
    • Consequence: Some operations (sorting, grouping) cannot be done efficiently without breaking the pipeline abstraction

🚫Non-goals (don't propose these)

  • Real-time streaming or event-driven I/O (blocking operations only)
  • Complex shell features like job control, process groups, or signal handling
  • Full POSIX shell compatibility (uses mvdan.cc/sh subset)
  • Distributed or parallel execution across machines

⚠️Anti-patterns to avoid

  • Silent error accumulationscript.go (Pipe.err field and all methods): Errors are silently stored in Pipe.err and only surface when Error() or String() is called; intermediate operations don't short-circuit, making debugging harder if

🪤Traps & gotchas

None obvious. Behavior is deterministic across platforms via explicit Unix/Windows test branching. No hidden env vars, no external service dependencies. One subtle point: shell metacharacters in arguments passed to Exec() are handled by mvdan.cc/sh—ensure quoting matches your intent (see testdata/script/*.txtar for examples).

🏗️Architecture

💡Concepts to learn

  • Unix Pipes and Streams — script.go's entire design philosophy mirrors Unix pipes—understanding how data flows through stdin/stdout/stderr and how programs compose via readers/writers is essential to using the API idiomatically
  • Fluent Interface / Method Chaining — The Pipe type returns itself from every method, enabling the ergonomic File().Match().CountLines() syntax; recognizing this pattern helps predict API behavior and extend it
  • io.Reader Interface — Pipe wraps an io.Reader and passes it through transformations; understanding this fundamental Go interface lets you hook in custom readers or integrate with other libraries
  • Shell Metacharacter Escaping — Exec() uses mvdan.cc/sh to parse shell syntax safely; knowing how quoting and escaping work (single vs. double quotes, $-expansion) prevents injection bugs
  • jq Query Language — The JQ() method applies jq transformations to JSON streams; familiarity with jq syntax (path expressions, filters, pipes) is required to use this effectively
  • Go Context Timeout and Cancellation — Although not visible in the file structure, Exec() integrates with context.Context for subprocess lifecycle; understanding context is crucial for production scripts that need timeout/cancellation
  • Cross-Platform File Path Handling — The Unix/Windows test split shows that filepath.Separator, path escaping, and process quoting differ—writing portable scripts requires attention to platform-specific behavior
  • mvdan/sh — Direct dependency (mvdan.cc/sh) for shell lexing and parsing; used by script.Exec() to safely interpret shell commands
  • itchyny/gojq — Direct dependency for JQ() method; provides jq-compatible JSON querying within Go pipelines
  • google/go-cmp — Testing dependency used in script_test.go for deep equality assertions; required for verifying complex output
  • golang/go — Core runtime; script.go relies heavily on io.Reader/Writer composition and os/exec patterns from stdlib
  • bitfield/testing — Companion testing utilities by the same author (bitfield) for assertions and test helpers in Go; often paired with script for integration test suites

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive Windows-specific pipe and stream handling tests in script_windows_test.go

The repo has script_unix_test.go with platform-specific tests, but script_windows_test.go likely has minimal coverage. Windows handles pipes, stdin/stdout, and process termination differently than Unix. Given the testdata/script/*.txtar files exist for testing argument and stdin piping, these scenarios should be explicitly validated on Windows to prevent cross-platform regressions.

  • [ ] Review existing testdata/script/args_sends_arguments_to_pipe.txtar and testdata/script/stdin_sends_stdin_to_pipe.txtar test cases
  • [ ] Add Windows-specific tests in script_windows_test.go covering: pipe buffering behavior, line ending handling (CRLF vs LF), subprocess signal handling on Windows, and output stream ordering under concurrent operations
  • [ ] Ensure tests validate that script.go's pipe implementations handle Windows limitations around process cleanup and I/O redirection

Add integration tests using txtar format for complex piping scenarios in testdata/script/

The repo has script/args_sends_arguments_to_pipe.txtar and script/stdin_sends_stdin_to_pipe.txtar, suggesting txtar-based integration tests exist. However, critical piping scenarios are missing: (1) error propagation through multi-stage pipes, (2) handling of binary data in pipes, (3) large file streaming, and (4) concurrent read/write operations. These should be added as txtar files and tested with the go-internal/txtar testing framework already in dependencies.

  • [ ] Create testdata/script/error_propagation_through_pipes.txtar testing failure handling across multiple pipe stages
  • [ ] Create testdata/script/large_file_streaming.txtar validating memory efficiency with multi-GB files
  • [ ] Create testdata/script/concurrent_pipe_operations.txtar for race condition detection
  • [ ] Add corresponding test cases in script_test.go that load and execute these txtar scenarios

Add GitHub Action workflow for testing against multiple Go versions (1.18+) in .github/workflows/

The repo specifies go 1.18 as minimum, but ci.yml likely tests only the latest or a single version. The go-cmp, gojq, and sh/v3 dependencies may have compatibility issues across Go 1.18, 1.19, 1.20, 1.21+. A matrix workflow would catch version-specific regressions early and signal compatibility guarantees to users.

  • [ ] Create .github/workflows/test-versions.yml with a matrix strategy for go-version: ['1.18', '1.19', '1.20', '1.21', 'latest']
  • [ ] Run 'go test ./...' and 'go vet ./...' for each version
  • [ ] Ensure testdata files and platform-specific tests (script_unix_test.go, script_windows_test.go) execute in the matrix across linux, windows, and macos runners

🌿Good first issues

  • Add a Reverse() method that reverses line order in the pipeline—requires implementing a buffering strategy in script.go and adding tests in script_test.go
  • Document and test the jq integration more thoroughly—testdata/ lacks .json examples for JQ() method; add fixture files and integration tests in script_test.go
  • Extend Windows tests (script_windows_test.go) to cover edge cases like UNC paths (\server\share) and PowerShell-specific quoting in Exec()

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 646fe23 — add links to readme (#234) (bitfield)
  • 6006cd0 — update changelog (#228) (bitfield)
  • 348e77b — Change JQ to process newline-delimited JSON (#227) (tho)
  • 5b2f8f4 — Add go-script to readme (#222) (bitfield)
  • 50f0076 — Tools (#220) (bitfield)
  • 29d5eb2 — update readme (#219) (bitfield)
  • bf66ef5 — Make FindFiles ignore (trivial) errors (#217) (mahadzaryab1)
  • dd8d444 — Slice now produces empty pipe for empty slice (fixes #110) (#216) (mahadzaryab1)
  • 6fff62a — Add Hash / HashSums (#215) (mahadzaryab1)
  • 0296fd2 — release v0.23 (bitfield)

🔒Security observations

The bitfield/script project has a generally acceptable security posture for a shell scripting library, but has several outdated dependencies that should be updated immediately. The primary concern is that Go 1.18 is end-of-life and golang.org/x/sys v0.10.0 is significantly outdated. While the library itself appears to follow good practices based on the file structure (includes tests, CI/CD automation), users must be cautious about command injection risks when using this library with untrusted input. No hardcoded secrets, exposed credentials, or major architectural security issues were detected. Updating dependencies and adding a security policy would improve the overall security posture.

  • High · Outdated Go Version — go.mod. The project targets Go 1.18, which reached end-of-life in September 2023. Using outdated Go versions exposes the project to known security vulnerabilities and missing security patches in the standard library. Fix: Update go.mod to target Go 1.21 or later (preferably 1.22+). Review and test compatibility with the newer version.
  • High · Vulnerable Dependency: golang.org/x/sys — go.mod (indirect dependency). The dependency golang.org/x/sys v0.10.0 (from August 2023) is outdated. This package contains system-level APIs and may have unpatched security vulnerabilities. Fix: Update golang.org/x/sys to v0.17.0 or later. Run 'go get -u golang.org/x/sys' and verify tests pass.
  • Medium · Vulnerable Dependency: golang.org/x/tools — go.mod (indirect dependency). The dependency golang.org/x/tools v0.11.0 (from August 2023) is outdated. While primarily a development tool, it may contain security issues affecting code analysis. Fix: Update golang.org/x/tools to v0.17.0 or later to receive security patches and improvements.
  • Medium · Potential Command Injection via Shell Execution — script.go (core library functionality). This library (script) is designed to execute shell commands and subprocesses. While the library itself may be well-designed, applications using it must be extremely careful about passing untrusted input to shell execution functions, as this could lead to command injection vulnerabilities. Fix: Document command injection risks clearly in the README and examples. Recommend users validate and sanitize all inputs before passing to shell execution methods. Consider providing safe alternatives that avoid shell interpretation.
  • Low · Missing Security Policy — Repository root. The repository does not contain a SECURITY.md file, which should outline the project's vulnerability disclosure policy and security contact information. Fix: Create a SECURITY.md file following GitHub's recommended format (https://docs.github.com/en/code-security/getting-started/adding-a-security-policy-to-your-repository) with responsible disclosure guidelines.
  • Low · No Dependency Pinning in CI/CD — .github/workflows/audit.yml. The audit.yml workflow may not be pinning dependency versions, which could lead to transitive dependency changes causing unexpected behavior. Fix: Ensure go.sum is committed and CI/CD workflows run 'go mod verify' to detect unexpected changes. Consider using 'go mod tidy' in CI to ensure consistency.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · bitfield/script — RepoPilot