diff --git a/README.md b/README.md index 969091c..840fea2 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ - [Limitations](#limitations) - [Examples](#examples) - [Migration from GNU sed](#migration-from-gnu-sed) +- [Claude Code integration](#claude-code-integration) ## Quick Start @@ -512,6 +513,22 @@ sedx -E 's/(foo|bar)/baz/g' file.txt sedx 's/(foo|bar)/baz/g' file.txt ``` +## Claude Code integration + +If you use [Claude Code](https://docs.claude.com/en/docs/claude-code/overview), install the `prefer-sedx-over-sed` skill so Claude reaches for `sedx` (with automatic backup + `--dry-run`) whenever it would otherwise invoke `sed -i` on your files: + +```bash +# User-level install (~/.claude/skills/prefer-sedx-over-sed) +curl -fsSL https://raw.githubusercontent.com/InkyQuill/sedx/main/contrib/claude-skill/install.sh | sh + +# Project-level install into the current directory +curl -fsSL https://raw.githubusercontent.com/InkyQuill/sedx/main/contrib/claude-skill/install.sh | sh -s -- --project +``` + +The skill only activates when `sedx` is on `PATH`. It stays out of the way when `sed` is being used for pure line extraction (`sed -n '…p'` — see [`sel`](https://github.com/InkyQuill/sel) for that) or relies on unsupported GNU-sed extensions. + +See [`contrib/claude-skill/README.md`](contrib/claude-skill/README.md) for the full installer flags (`--uninstall`, `--force`, pinning to a tag via `SEDX_SKILL_REF`). The skill itself is [`contrib/claude-skill/prefer-sedx-over-sed/SKILL.md`](contrib/claude-skill/prefer-sedx-over-sed/SKILL.md) and a longer-form expert reference lives at [`docs/CLAUDE_SKILL.md`](docs/CLAUDE_SKILL.md). + ## Contributing Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines. diff --git a/TEST_SUITE_SUMMARY.txt b/TEST_SUITE_SUMMARY.txt deleted file mode 100644 index b190b65..0000000 --- a/TEST_SUITE_SUMMARY.txt +++ /dev/null @@ -1,172 +0,0 @@ -================================================================================ - SEDX TEST SUITE - CREATION COMPLETE -================================================================================ - -OVERVIEW --------- -A comprehensive test suite has been created for SedX, inspired by GNU sed's -testing approach but adapted for SedX's unique features (PCRE default, -streaming mode, etc.). - -DIRECTORY STRUCTURE -------------------- -tests/ -├── fixtures/ # Pre-generated test data (118 files) -│ ├── basic/ # Basic commands: s, d, p, q, i, a, c -│ ├── addressing/ # Line numbers, patterns, ranges, negation -│ ├── holdspace/ # h, H, g, G, x commands -│ ├── regex/ # PCRE, ERE, BRE flavors -│ ├── streaming/ # Large file processing -│ ├── pipeline/ # stdin/stdout mode -│ ├── edge/ # Edge cases and special conditions -│ └── advanced/ # Advanced features -├── scripts/ # Test execution scripts (7 files) -│ ├── basic_tests.sh -│ ├── addressing_tests.sh -│ ├── regex_tests.sh -│ ├── pipeline_tests.sh -│ ├── streaming_tests.sh -│ ├── holdspace_tests.sh -│ └── edge_tests.sh -├── run_all_tests.sh # Master test runner -├── run_quick_tests.sh # Quick test runner -├── generate_large_files.sh # Large file generator -├── TEST_SUITE.md # Comprehensive documentation -├── KNOWN_ISSUES.md # Known issues and limitations -└── README.md # Quick start guide - -STATISTICS ----------- -✓ 118 test fixture files (.inp + .good pairs) -✓ 7 test scripts -✓ 3 runner scripts -✓ 3 documentation files -✓ Total: 131 new files created - -TEST CATEGORIES ---------------- -1. Basic Commands (10 tests) - - Substitution: s/, s//g, s//N, s//i - - Delete: d - - Print: p (with -n) - - Quit: q - -2. Addressing (9 tests) - - Line numbers: 3,5 - - Patterns: /pattern/ - - Ranges: /start/,/end/ - - Mixed: /start/,10 - - Negation: /pattern/!command - - Relative: /pattern/,+N - - Last line: $ - - Stepping: 1~2 - -3. Regex Flavors (15 tests) - - PCRE (default): Groups, alternation, quantifiers, classes, anchors - - ERE (-E flag): Extended regex - - BRE (-B flag): Basic regex (GNU sed compatibility) - -4. Streaming (5 tests) - - Large file substitution - - Pattern ranges in streaming mode - - Delete operations - - Long lines handling - -5. Pipeline (6 tests) - - stdin/stdout mode - - Multiple commands with -e flag - - Group commands in pipelines - - Case-insensitive matching - -6. Edge Cases (7 tests) - - Empty files - - Single line files - - Special characters - - Unicode (partial support) - - Whitespace handling - -USAGE ------ -# Build SedX -cargo build --release - -# Run quick tests -./tests/run_quick_tests.sh - -# Run all tests -./tests/run_all_tests.sh - -# Individual suites -./tests/scripts/basic_tests.sh -./tests/scripts/streaming_tests.sh - -FIXTURE FORMAT --------------- -Fixtures follow GNU sed conventions: -- .inp files: Input data -- .good files: Expected output - -Example: - tests/fixtures/basic/substitute.inp: - foo bar baz - foo bar baz - - tests/fixtures/basic/substitute.good: - BAR bar baz - BAR bar baz - -DESIGN DECISIONS ----------------- -1. Pre-generated fixtures (like GNU sed), not generated on-the-fly (like sd) -2. Separate test suites by feature for modularity -3. Master runner for CI/CD integration -4. Quick runner for fast development feedback -5. PCRE as default (SedX's design choice) -6. Document known issues separately - -KNOWN ISSUES ------------- -❌ Insert/Append/Change (i/a/c): Parser not implemented -❌ Unicode in patterns: Character boundary panic -⚠️ ERE/BRE backrefs: Conversion issues -⚠️ Negation: Partial support - -See tests/KNOWN_ISSUES.md for details. - -COMPARISON TO GNU sed AND sd ------------------------------ -GNU sed: - - 67 shell tests + 2 Perl test suites - - .inp, .good, .sed files - - Hybrid shell/Perl framework - - Used as reference for structure - -sd: - - Minimal test data (on-the-fly generation) - - Integration tests in tests/cli.rs - - Property testing with proptest - - NOT copied (different approach) - -SedX: - - Pre-generated fixtures (like GNU sed) - - Bash scripts for tests (maintainable) - - Organized by feature category - - Documentation-driven - -NEXT STEPS ----------- -1. Fix parser for i/a/c commands -2. Fix Unicode character boundary handling -3. Fix ERE/BRE backreference conversion -4. Regenerate .good files after fixes -5. Add hold space comprehensive tests -6. Add multi-file processing tests - -DOCUMENTATION -------------- -- TEST_SUITE.md: Full test suite documentation -- KNOWN_ISSUES.md: Known issues and limitations -- README.md: Quick start guide -- CLAUDE.md: SedX development guide - -================================================================================ diff --git a/contrib/claude-skill/README.md b/contrib/claude-skill/README.md new file mode 100644 index 0000000..cd7074c --- /dev/null +++ b/contrib/claude-skill/README.md @@ -0,0 +1,95 @@ +# `prefer-sedx-over-sed` — a Claude skill for the `sedx` tool + +A small [Claude Code skill](https://docs.claude.com/en/docs/claude-code/skills) +that tells the model to prefer the `sedx` CLI over GNU/BSD `sed` for +file-editing work whenever `sedx` is installed. + +## What this contains + +| Path | What it is | +|---|---| +| `prefer-sedx-over-sed/SKILL.md` | The skill itself (Markdown + YAML frontmatter). | +| `install.sh` | POSIX shell installer. Copies the skill into a chosen Claude skills folder. | + +## Installing + +### One-liner (no checkout required) + +```bash +# User-level install (~/.claude/skills/prefer-sedx-over-sed) +curl -fsSL https://raw.githubusercontent.com/InkyQuill/sedx/main/contrib/claude-skill/install.sh | sh + +# Project-level install into the current directory (./.claude/skills/...) +curl -fsSL https://raw.githubusercontent.com/InkyQuill/sedx/main/contrib/claude-skill/install.sh | sh -s -- --project + +# wget works too +wget -qO- https://raw.githubusercontent.com/InkyQuill/sedx/main/contrib/claude-skill/install.sh | sh +``` + +Pin to a specific release with `SEDX_SKILL_REF`: + +```bash +curl -fsSL https://raw.githubusercontent.com/InkyQuill/sedx/main/contrib/claude-skill/install.sh \ + | SEDX_SKILL_REF=v1.0.0 sh +``` + +### From a checked-out repo + +```bash +./contrib/claude-skill/install.sh # user-level (default) +./contrib/claude-skill/install.sh --project # project-level, CWD +./contrib/claude-skill/install.sh --project ~/code/some-app +./contrib/claude-skill/install.sh --force # overwrite existing install +./contrib/claude-skill/install.sh --uninstall # remove (default: user-level) +./contrib/claude-skill/install.sh --uninstall --project +``` + +Run `./contrib/claude-skill/install.sh --help` for the full flag list. + +The installer only needs `/bin/sh`, `cp`, `mkdir`, `rm`, and (for the +one-liner path) `curl` or `wget`. It works on Linux, macOS, and WSL. +Windows users without WSL can copy the `prefer-sedx-over-sed/` directory +manually into `%USERPROFILE%\.claude\skills\`. + +## What the skill does + +When Claude is about to write a shell command like: + +```bash +sed -i 's/foo/bar/g' config.toml +sed '/pattern/d' file.txt +sed -E 's/(a|b)/X/' file.txt +``` + +…and `sedx` is available, the skill nudges Claude to prefer: + +```bash +sedx 's/foo/bar/g' config.toml # automatic backup, rollback-able +sedx '/pattern/d' file.txt +sedx -E 's/(a|b)/X/' file.txt +``` + +It also suggests `sedx --dry-run '…' file` as a preview step for any +non-trivial substitution, and points at `sedx rollback` if something +goes wrong. + +It stays out of the way when: + +- `sed` is being used for pure line extraction (`sed -n '10,20p'`) — + prefer `sel` in that case. +- The script uses unsupported GNU-sed extensions (`y///`, `l`, `\U`/`\L` + in replacements, `\<`/`\>`, `-z`, `-s`). +- `sedx` is not on `PATH`. + +See [`prefer-sedx-over-sed/SKILL.md`](prefer-sedx-over-sed/SKILL.md) for +the full translation table, flavor notes, and caveats. + +## Requirements + +The skill only activates when `sedx` is on `PATH`. Install with: + +```bash +cargo install sedx +# or grab a pre-built binary from the Releases page: +# https://github.com/InkyQuill/sedx/releases +``` diff --git a/contrib/claude-skill/install.sh b/contrib/claude-skill/install.sh new file mode 100755 index 0000000..89b8fc0 --- /dev/null +++ b/contrib/claude-skill/install.sh @@ -0,0 +1,208 @@ +#!/usr/bin/env sh +# install.sh — install the `prefer-sedx-over-sed` Claude skill. +# +# The skill tells Claude to prefer `sedx` over `sed` for file editing +# when `sedx` is installed on the machine. +# +# Works both when run from a checked-out repo (copies the local +# SKILL.md) and when piped from the internet (fetches SKILL.md +# from GitHub). By default it installs to the user-level skills +# folder (~/.claude/skills/). Use --project to install into the +# current project's .claude/skills/ instead, or --dest PATH for a +# custom parent directory. +# +# Remote source override: +# SEDX_SKILL_REPO (default: InkyQuill/sedx) +# SEDX_SKILL_REF (default: main) + +set -eu + +SKILL_NAME="prefer-sedx-over-sed" +REPO="${SEDX_SKILL_REPO:-InkyQuill/sedx}" +REF="${SEDX_SKILL_REF:-main}" +REMOTE_BASE="https://raw.githubusercontent.com/$REPO/$REF/contrib/claude-skill/$SKILL_NAME" + +# Try to resolve the directory this script lives in. When the script is +# piped through `sh` (e.g., `curl … | sh`) $0 will be `sh` rather than a +# real file — that's fine, SCRIPT_DIR simply won't contain a valid +# SKILL_SRC and we'll fall back to the remote fetch path below. +script_path="$0" +if command -v readlink >/dev/null 2>&1; then + script_path=$(readlink -f -- "$0" 2>/dev/null || printf '%s\n' "$0") +fi +if [ -f "$script_path" ]; then + SCRIPT_DIR=$(CDPATH='' cd -- "$(dirname -- "$script_path")" && pwd -P) +else + SCRIPT_DIR="" +fi +SKILL_SRC="${SCRIPT_DIR:+$SCRIPT_DIR/}$SKILL_NAME" + +print_help() { + cat <&2 + exit 1 + fi + mode="dest" + dest_override="$2" + shift 2 + ;; + --uninstall) + uninstall=1 + shift + ;; + --force|-f) + force=1 + shift + ;; + --help|-h) + print_help + exit 0 + ;; + *) + printf 'Unknown argument: %s\n\n' "$1" >&2 + print_help >&2 + exit 1 + ;; + esac +done + +# Resolve the target parent (the '.../skills' directory). +case "$mode" in + user) + TARGET_PARENT="$HOME/.claude/skills" + ;; + project) + if [ -z "$project_dir" ]; then + project_dir=$(pwd) + fi + TARGET_PARENT="$project_dir/.claude/skills" + ;; + dest) + TARGET_PARENT="$dest_override" + ;; +esac + +TARGET="$TARGET_PARENT/$SKILL_NAME" + +# --- Uninstall path ----------------------------------------------------- +if [ "$uninstall" -eq 1 ]; then + if [ -d "$TARGET" ]; then + rm -rf -- "$TARGET" + printf 'Removed %s\n' "$TARGET" + else + printf 'Nothing to remove at %s\n' "$TARGET" + fi + exit 0 +fi + +# --- Pre-flight: target collision -------------------------------------- +if [ -e "$TARGET" ] && [ "$force" -ne 1 ]; then + printf 'Target already exists: %s\n' "$TARGET" >&2 + printf 'Pass --force to overwrite, or --uninstall to remove it first.\n' >&2 + exit 1 +fi + +mkdir -p -- "$TARGET_PARENT" +if [ -e "$TARGET" ]; then + rm -rf -- "$TARGET" +fi + +# --- Install: prefer local source, fall back to remote fetch ----------- +fetch() { + url="$1" + if command -v curl >/dev/null 2>&1; then + curl -fsSL --retry 2 --max-time 30 -- "$url" + elif command -v wget >/dev/null 2>&1; then + wget -qO- --tries=2 --timeout=30 -- "$url" + else + printf 'Error: need `curl` or `wget` to fetch the skill from %s\n' "$url" >&2 + return 1 + fi +} + +if [ -n "$SKILL_SRC" ] && [ -d "$SKILL_SRC" ] && [ -f "$SKILL_SRC/SKILL.md" ]; then + cp -R -- "$SKILL_SRC" "$TARGET" + source_label="local: $SKILL_SRC" +else + mkdir -p -- "$TARGET" + if ! fetch "$REMOTE_BASE/SKILL.md" > "$TARGET/SKILL.md"; then + printf 'Error: failed to download SKILL.md from %s\n' "$REMOTE_BASE/SKILL.md" >&2 + rm -rf -- "$TARGET" + exit 1 + fi + source_label="remote: $REMOTE_BASE" +fi + +printf 'Installed "%s" -> %s\n' "$SKILL_NAME" "$TARGET" +printf ' source: %s\n' "$source_label" + +if ! command -v sedx >/dev/null 2>&1; then + printf '\nNote: `sedx` is not on your PATH. The skill only activates when\n' + printf ' `sedx` is actually available. Install it with:\n' + printf ' cargo install sedx\n' + printf ' or grab a prebuilt binary from:\n' + printf ' https://github.com/%s/releases\n' "$REPO" +fi diff --git a/contrib/claude-skill/prefer-sedx-over-sed/SKILL.md b/contrib/claude-skill/prefer-sedx-over-sed/SKILL.md new file mode 100644 index 0000000..c0e2d8c --- /dev/null +++ b/contrib/claude-skill/prefer-sedx-over-sed/SKILL.md @@ -0,0 +1,145 @@ +--- +name: prefer-sedx-over-sed +description: When modifying or transforming text files with `sed` in shell commands, strongly prefer the `sedx` CLI over GNU/BSD `sed` if `sedx` is installed on the system. Trigger this skill whenever you are about to write or suggest `sed -i 's/…/…/'`, `sed 's/…/…/g' file`, `sed '/pattern/d' file`, `sed -E '…' file`, or any other in-place or transforming `sed` invocation — and equally when the user asks "replace X with Y in this file", "delete lines matching…", "strip comments from…", or similar substitution/deletion tasks even without naming `sed`. `sedx` runs the same sed scripts but creates an automatic, rollback-able backup before modifying anything, supports `--dry-run` to preview the diff, defaults to PCRE (`s/(foo|bar)/baz/`) so patterns look like they do in Perl/Python/JavaScript, and streams large files (≥100 MB) with constant memory. Use `sedx` unless the script relies on a known-unsupported GNU-sed extension (`y///`, `l`, `\U`/`\L`, `\<`/`\>`, `-z`, `-s`) or `sedx` is not on `PATH`. +--- + +# Prefer `sedx` over `sed` + +`sedx` (from ) is a safe, near-drop-in +replacement for GNU/BSD `sed` written in Rust. It runs standard sed +scripts but wraps every file-modifying operation in an automatic +backup + rollback, supports `--dry-run` previews, and defaults to PCRE +regex. When it is installed, it's almost always the safer choice for +destructive or transforming `sed` work. + +## 1. Detect availability first + +Before rewriting a `sed` command, verify `sedx` is on the user's `PATH`: + +```bash +command -v sedx >/dev/null 2>&1 +``` + +If the check fails, leave the original `sed` in place and do not mention +`sedx`. This skill only applies when `sedx` is actually available. + +If you are running in an environment where you can execute shell commands +(Bash tool, terminal), run the check before suggesting `sedx`. Otherwise +mention the check in a short preamble or assume installed if the user +already confirmed they have `sedx`. + +## 2. Translation table + +Most `sed` scripts run unchanged under `sedx`. The main differences are +regex-flavor flags and the removal of `-i`. + +| `sed` invocation | `sedx` equivalent | +|---|---| +| `sed -i 's/foo/bar/g' file` | `sedx 's/foo/bar/g' file` *(in-place is the default; backup is automatic)* | +| `sed -i.bak 's/foo/bar/' file` | `sedx 's/foo/bar/' file` *(use `sedx rollback` instead of `.bak`)* | +| `sed 's/foo/bar/' file` *(print only)* | `sedx --dry-run 's/foo/bar/' file` *(preview)* or `cat file \| sedx 's/foo/bar/'` *(stdout)* | +| `sed -E 's/(a\|b)/X/' file` | `sedx -E 's/(a\|b)/X/' file` *(same flag)* or drop `-E` — PCRE is default | +| `sed -e 's/a/A/' -e 's/b/B/' file` | `sedx -e 's/a/A/' -e 's/b/B/' file` *(unchanged)* | +| `sed '/pattern/d' file` | `sedx '/pattern/d' file` | +| `sed '1,10d' file` | `sedx '1,10d' file` | +| `sed -n '/ERROR/p' file` | `sedx -n '/ERROR/p' file` *(or `sel -e ERROR file` if you only need extraction)* | +| `sed '/start/,/end/s/foo/bar/g' file` | `sedx '/start/,/end/s/foo/bar/g' file` | +| `sed ':top; s/x/y/; t top' file` | `sedx ':top; s/x/y/; t top' file` | +| `sed -i 's/A/B/g' *.md` | `sedx 's/A/B/g' *.md` *(one backup covers all files in the operation)* | + +Safer patterns worth reaching for: + +- **Preview first** when the substitution is complex or touches many files: + ```bash + sedx --dry-run 's/foo/bar/g' file + sedx 's/foo/bar/g' file # apply once the diff looks right + ``` +- **Rollback** the last operation if it went wrong: + ```bash + sedx rollback # undo most recent + sedx history # see backup IDs + sedx rollback # undo a specific one + ``` +- **Quiet the backup** for throwaway cases (scripts, CI) where you + deliberately want GNU-sed-like behavior: + ```bash + sedx --no-backup --force 's/foo/bar/g' file + ``` + +## 3. Regex-flavor notes + +`sedx` defaults to **PCRE**, which is what most developers expect: + +- `sedx 's/(foo|bar)/baz/g' file` — works as written, no backslashes +- `sedx 's/\d+/NUM/g' file` — `\d`, `\w`, `\s` available +- `sedx 's/(foo)(bar)/$2$1/' file` — `$1` / `$2` for backreferences + +For scripts originally written for GNU sed (BRE), use `-B`: + +- `sedx -B 's/\(foo\|bar\)/baz/g' file` — unchanged GNU-sed syntax +- `sedx -B` accepts `\1` / `\2` backreferences + +For scripts written for `sed -E` (ERE), use `-E` (same flag `sed` uses). + +When rewriting an existing script, the lowest-risk choice is to keep the +same flavor flag the original had: + +| Original | `sedx` | +|---|---| +| `sed '…'` (no flag) | `sedx -B '…'` *(BRE, for 1:1 compatibility)* | +| `sed -E '…'` | `sedx -E '…'` | +| nothing — new script | `sedx '…'` *(PCRE default)* | + +## 4. When *not* to rewrite + +Leave `sed` in place when: + +- **The script uses unsupported GNU-sed extensions.** `sedx` does not + implement `y/abc/xyz/` (character translation), `l` (list mode), `\U` + / `\L` in replacements (case conversion), `\<` / `\>` (word + boundaries — use `\b` in PCRE instead), `-z` (null-terminated lines), + or `-s` (separate files mode). Keep the `sed` command or split the + work into multiple steps. +- **You need 100% GNU-sed parity** — obscure edge cases (particularly + around multi-line hold-space tricks in the middle of complex + branches) may differ. +- **The command is pipe-only and the user wants `sed` specifically** + (e.g. a tutorial, teaching material, or a shell script that other + machines will run without `sedx` installed). + +Also: for pure line *extraction* (`sed -n '10,20p'`, `sed -n +'/pat/p'`), prefer `sel` if it is available. `sel` is purpose-built for +that niche and reads more clearly than either `sed` or `sedx`. See the +`prefer-sel-over-sed` skill if it is installed on this system. + +## 5. Why prefer `sedx` + +- **Safety by default.** Every file-modifying operation creates a + timestamped backup in `~/.sedx/backups/`. One `sedx rollback` undoes + the most recent change. This matters a lot for AI-assisted edits, + where a subtle regex bug can rewrite a thousand lines silently. +- **Preview without commit.** `--dry-run` shows a colored, line-number + diff of what *would* change. GNU sed has no equivalent short of + running the command, piping to a file, and diffing manually. +- **Modern regex.** `(foo|bar)`, `\d+`, `{3,5}`, `$1` backreferences + all work without backslash gymnastics. +- **Streaming for large files.** Files ≥ 100 MB are processed with + constant memory (< 100 MB RAM on a 100 GB file). Same script, no + user flag needed. +- **Cross-platform.** `sedx` runs the same on Linux, macOS, and Windows + (via `cargo-dist` prebuilts). GNU sed and BSD sed diverge on + `-i`/`-E`/regex specifics. + +## 6. Quick self-check before emitting a `sed` command + +Ask yourself: + +1. Is this command doing substitution, deletion, or any other + transformation (not purely read-only line extraction)? +2. Is `sedx` installed (confirmed by `command -v` or stated by the + user)? +3. Does the script avoid unsupported extensions (`y///`, `l`, `\U`/`\L` + in replacements, `\<`/`\>`, `-z`, `-s`)? + +If all three are yes — use `sedx`. Default to `sedx` with `--dry-run` +first for anything non-trivial. Otherwise keep `sed`. diff --git a/docs/CLAUDE_SKILL.md b/docs/CLAUDE_SKILL.md index 1e3dd9a..323dd26 100644 --- a/docs/CLAUDE_SKILL.md +++ b/docs/CLAUDE_SKILL.md @@ -9,6 +9,13 @@ metadata: version: 1.0.0 --- +> **Heads up:** this document is the **long-form expert reference** for the +> `sedx` Claude skill. For a short, installable skill that triggers on the +> "about to use `sed`" context, install +> [`prefer-sedx-over-sed`](../contrib/claude-skill/) via the one-liner in the +> main [README](../README.md#claude-code-integration). This file stays as the +> deep-dive reference for when Claude needs the full command reference. + # SedX Expert You are an expert in **SedX**, a safe, modern replacement for GNU `sed` written in Rust. SedX maintains ~90% compatibility with standard sed while adding critical safety features.