Skip to content

Agent Integration

Mikhail Deynekin edited this page Oct 9, 2026 · 2 revisions

Agent Integration — using Clean BOM Senior from an LLM agent

This page is for people who wire this tool into an LLM coding agent (DeepSeek Harness, Claude Code, Cursor, a home-grown harness), and for the agents themselves. It covers the two things that decide whether the rule actually holds: where the rule lives and which implementation to call on which platform.

Everything here was measured on v3.0.0 (2026-10-09) against this repository.

Rule in two places, not one

Where What goes there Why
A skill — skills/clean-bom-crlf/SKILL.md the full procedure: install, per-platform entry point, the decision table, exceptions, byte-level verification, exit codes a skill loads when the task touches files, so the long text costs nothing until it is needed
The agent's always-loaded rules (system prompt, AGENTS.md, CLAUDE.md…) one pointer sentence naming the skill an always-present line is what makes the agent think to load the skill

A skill alone is unreliable — nothing reminds the agent it exists. A rule alone is expensive and gets duplicated. Together they work like a loader plus a check.

Pointer sentence to paste into the rules file:

Any task that touches code or text files (create, edit, generate, patch, package: .php .js .css .html .xml .sh .py .yaml .json .ps1 .md .txt …) — load and follow the clean-bom-crlf skill before delivering the result.

A ready-made prompt for a foreign agent (it creates the skill, adds the pointer, verifies both are visible, and reports four concrete facts) lives in docs/PROMPT-OTHER-HARNESS.md.

Where to put the skill

Copy the directory (a skill is a directory containing SKILL.md):

$DSH_HOME/skills/clean-bom-crlf/SKILL.md      # DeepSeek Harness
~/.claude/skills/clean-bom-crlf/SKILL.md      # Claude Code and compatible agents
<repo>/.agent/skills/clean-bom-crlf/SKILL.md  # project-local, travels with the repo

An agent with no skill mechanism at all can take the body of SKILL.md as a section of its rules file — the content does not depend on a loader.

When the rule applies

Every file that stays behind: created, edited, generated, patched or packaged, and left in a repository or shipped in a build, ends at BOM=False, CRLF=False — except the deliberate exceptions below.

Two failure modes look exactly like success:

  • running the tool with no arguments — it then walks the current directory and can rewrite files unrelated to the task;
  • running it against a directory while files use an extension outside the default set (php css js txt xml htm html) — they are skipped silently while the report still says "done".

Which implementation to call

Platform Command Notes
Linux, macOS, WSL, Git Bash bash clean-bom-senior.sh --quiet <files…> POSIX shell, GNU and BSD userland, no extra runtime
Windows pwsh -NoLogo -NoProfile -File clean-bom-senior.ps1 --quiet <files…> requires PowerShell 7.0+ (Core); pure .NET byte I/O, no Git Bash needed
Any host with Node ≥ 18 node bin/bom.js --quiet <files…> fallback for Windows without PowerShell 7
Any, without writing --check exit 10 = needs cleaning, 0 = clean

Parity is asserted, not assumed: sh↔node over 8 fixtures, sh↔ps1 over 77 scenarios.

Installing it when an agent does not have it

The repository is public, so an agent can fetch a pinned revision and verify it. Pin a commit, not main, or the instruction silently ages:

PIN=c799d11635a22e6abccd903e534dd84a409117a2
curl -fsSL -o clean-bom-senior.sh \
  "https://raw.githubusercontent.com/paulmann/Clean_BOM_Senior/$PIN/clean-bom-senior.sh"
printf '%s  %s\n' ec1634249bff874d10b0d2999760be603153b1f0fcccc06a5f6b0be667504693 clean-bom-senior.sh | sha256sum -c -
chmod +x clean-bom-senior.sh

Windows: fetch clean-bom-senior.ps1 and bin/bom.js the same way, and confirm PowerShell 7+ first — $PSVersionTable.PSVersion must print 7.x. On macOS use shasum -a 256 instead of sha256sum. If the checksum does not match, do not run the file; if there is no network, say so instead of imitating success.

Deciding what the tool will do (v3.0.0, measured)

Situation Result
UTF-8 BOM + code (php js css html xml sh py yaml json) BOM removed, CRLF→LF
UTF-8 BOM + pure-ASCII content (any extension) BOM removed
BOM + non-ASCII in txt csv tsv ps1 psm1 psd1 and any unknown extension (incl. md) BOM kept deliberately — Excel and PowerShell 5.1 need it; CRLF still normalised
the same + --bom-policy=strip / --force BOM removed
UTF-16/32 BOM, or NUL bytes anywhere never touched, even with --force
invalid UTF-8 untouched by default; --force = byte-level cleaning
file already clean never rewritten — inode and mtime unchanged

Exceptions — the expected result is inverted:

  • .bat, .cmd, .reg must keep CRLF (cmd.exe will not run an LF-only batch file). A plain call breaks them; if the BOM has to go, use --no-rn-normalize (measured: BOM removed, CRLF intact).
  • non-ASCII txt/csv/ps1/md keep their BOM by policy. Remove it knowingly — a #!/usr/bin/env pwsh script that must also run on Unix has to be ASCII without a BOM, otherwise the kernel reads the BOM as magic and runs /bin/sh.

Verify by bytes — a report is not evidence

$b = [IO.File]::ReadAllBytes('<file>')
$bom  = $b.Length -ge 3 -and $b[0] -eq 0xEF -and $b[1] -eq 0xBB -and $b[2] -eq 0xBF
$crlf = ([IO.File]::ReadAllText('<file>')) -match "`r`n"
"BOM=$bom CRLF=$crlf"     # expected False False, except for the exceptions above
head -c 3 '<file>' | od -An -tx1 | tr -d ' \n'   # must not be efbbbf
tr -dc '\r' < '<file>' | wc -c                   # must be 0

grep -c '\r' looks right and is wrong on GNU grep: \r is not a CR in a BRE, so the pattern degenerates to the letter r and a clean file reports a non-zero count (measured 1 on GNU 3.11/Debian). Use tr -dc '\r' | wc -c, or grep -c "`$(printf '\r')" with a real CR byte in the pattern.

Exit codes: 0 success · 1 per-file errors or --strict findings · 2 usage · 3 environment · 4 internal · 10 --check found dirt · 11 update available. Precedence: 2/3/4 > 1 > 10/11 > 0.

What an agent should report back

An agent claiming the rule is installed should return four facts: the path of the skill file and of the rules file, that both are UTF-8 without BOM and LF-only, the first lines of the rules section, and the output of --version. Without them, "the rule is installed" cannot be checked — and that is exactly where such setups usually fail quietly.

Clone this wiki locally