pi-charset
Encoding-aware read, write, edit, and grep extension for Pi
Package details
Install pi-charset from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:pi-charset- Package
pi-charset- Version
0.1.4- Published
- Oct 28, 2026
- Downloads
- 677/mo · 677/wk
- Author
- altior
- License
- MIT
- Types
- extension, skill, prompt
- Size
- 256.3 KB
- Dependencies
- 2 dependencies · 4 peers
Pi manifest JSON
{
"skills": [
"./skills/charset-rules"
],
"prompts": [
"./prompts/charset-setup.md"
],
"extensions": [
"./src/index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-charset
Encoding-aware read, write, edit, and grep extension for Pi (@earendil-works/pi-coding-agent).
English | 简体中文
Overview
pi-charset intercepts file I/O and search operations in Pi to handle repositories that mix GBK, GB18030, Big5, Shift_JIS, EUC-KR, ISO-8859-1, UTF-16, and UTF-8 files within the same workspace. All byte classification and transcoding run in-process without external Python or chardet subprocesses.
Working with a GBK Project
For an existing GBK project, run /charset-init --dry-run (or /charset-init embedded-c --dry-run) inside Pi to review the suggested rules before generating .pi-charset.json. Keep unmappable: "error" and verifyWrite: true: characters that GBK cannot represent should stop a write rather than turn into ?.
Use Pi's read, edit, and write tools for source changes. Shell redirection and external formatters bypass this extension. After installation, run /charset-status, edit a small tracked file, and inspect the diff in your usual editor before wider use.
Byte detection is not proof of an encoding: GBK and GB18030 overlap, and some bytes also decode under other encodings. For a project that requires GBK, declare GBK explicitly instead of relying on inference, especially for new or ASCII-only files. This extension prevents new encoding damage; it cannot reconstruct text that was already saved as question marks or mojibake.
Architecture
1. Deterministic Byte Classification
Files are classified in memory in a fixed order:
- BOM Detection:
UTF-8 BOM,UTF-16LE,UTF-16BE(UTF-32 BOMis classified asBINARY). - Binary Guard: Any
0x00byte within the first 8192 bytes classifies the file asBINARY. - Explicit
force: Rules withforce: trueapply the configured encoding directly. - Pure ASCII: Validated via Node's native
node:bufferisAscii(<= 0x7F). - Strict UTF-8: Full-buffer validation via Node's native
node:bufferisUtf8without heap string allocation. - Multi-Byte CJK Round-Trip: Candidates in
autoCandidatesare tested forencode(decode(bytes)) == byteswith zeroU+FFFDreplacement characters;sourceEncodingtakes priority when multiple candidates pass. - Fallback: Unclassified byte sequences are marked
UNKNOWN.
2. Write Safety Gates
- Gate 1 (Unmappable Code Points): Checks every code point against the target encoding before writing. Default policy
erroraborts the write and lists unmappable characters withU+XXXXcode points. Optional policies:escape(\uXXXX) anddrop-to-gb18030(promotes GB-family writes toGB18030). - Gate 2 (Pre-Write Round-Trip & Post-Write Read-Back): Verifies
decode(encode(text)) === textin memory before touching disk, then reads back the written file to verify byte and text equality. If post-write verification fails,pi-charsetreports the mismatch and preserves the on-disk file without rolling back to a stale backup. - Gate 3 (Unknown & Lossy Conversion Guard): Rejects writes to
BINARYorUNKNOWNfiles, preserves existingUTF-8files by default (protectUtf8: true), and rejects writes when existing on-disk bytes cannot losslessly round-trip in the target encoding.
3. Line Endings & Baseline Conflict Detection
- Line-Ending Preservation: Existing files keep their on-disk line endings (
CRLForLF, detected at the character level for UTF-16); files without newlines do not get trailing newlines appended. - Mixed Line-Ending Guard: Files containing both
CRLFandLFcan be read viaread, buteditandwriteare rejected. - New-File Line Endings: Configurable via
newFileLineEnding: "CRLF" | "LF"for newly created files. - Read Baseline Verification: Records a SHA-1 fingerprint when a managed file is read; rejects writes if the on-disk file was modified or deleted externally after the read.
4. Zero-Config Self-Adaptive Mode & Sibling Inference
pi-charset works out-of-the-box without requiring a .pi-charset.json file:
- Existing Files: Automatically read in their byte-classified encoding (
GBK,GB18030,Big5,UTF-16,UTF-8) and written back preserving their original encoding, line endings (CRLForLF), and BOM. - New & Pure-ASCII Files: When no
.pi-charset.jsonis present,pi-charsetinspects sibling files in the same directory (matching extension group first, e.g..c/.h) and inherits the dominant encoding and line-ending style (defaulting toUTF-8when siblings are UTF-8 or ASCII). - Multi-Encoding Search (
grep): Regex patterns and non-ASCII literals runUTF-8 + GB18030ripgreppasses in zero-config mode, or the configured candidate encodings when.pi-charset.jsonis present. Matches are verified against each file's classified encoding and deduplicated byfile:line.
Quick Start
1. Installation & Updates
# Install globally from npm (recommended; omit -l for global, add -l for project .pi/settings.json)
pi install npm:pi-charset
# Upgrade to the latest release at any time
pi update --extensions
# Or install directly from Git
pi install git:github.com/ethan-blue/pi-charset -l
2. Scaffold or Create .pi-charset.json
Inside a Pi session, generate .pi-charset.json directly with /charset-init (auto-scan or preset template):
/charset-scan # Read-only encoding & line-ending profile
/charset-scan --damaged # Check for pre-existing U+FFFD / mojibake files
/charset-init --dry-run # Preview auto-inferred config without writing disk
/charset-init # Generate .pi-charset.json from project declarations & bytes
/charset-init embedded-c # Or scaffold from preset: embedded-c | legacy-java-web | mixed-repo | all-utf8
/charset-setup # Prompt template: guided workspace audit + config preview
Or run the standalone CLI scanner outside Pi:
node tools/scan-encoding.mjs /path/to/project --init --dry-run
node tools/scan-encoding.mjs /path/to/project --init
Or create .pi-charset.json manually in the project root (JSONC comments supported):
{
"sourceEncoding": "UTF-8",
"writeEncoding": "UTF-8",
"unmappable": "error",
"verifyWrite": true,
"protectUtf8": true,
"readStrategy": "auto",
"autoCandidates": ["GB18030", "GBK", "GB2312", "Big5"],
"overrides": [
{
"pattern": "src/**/*.c",
"encoding": "GBK",
"writeEncoding": "GBK",
"newFileLineEnding": "CRLF"
},
{
"pattern": "src/**/*.h",
"encoding": "GBK",
"writeEncoding": "GBK",
"newFileLineEnding": "CRLF"
}
]
}
3. Diagnostics
Run inside a Pi session:
/charset-status
Scope & Boundaries
| Entry Point | Handled | Notes |
|---|---|---|
read, write, edit, grep tools |
Yes | Works out-of-the-box in zero-config adaptive mode; customizable via optional .pi-charset.json |
bash, powershell stdout/stderr |
Optional | Disabled by default; enable via transcodeBash: "auto" |
Shell output redirection (echo >, Set-Content) |
No | Bypasses file tools; use write or edit instead |
CLI startup @file arguments |
No | Read by the host before extensions load |
Atomic replacement avoids partially written files, but it is not a cross-process transaction or lock. Avoid editing the same file concurrently with external tools. Writes to symbolic links are rejected; edit the target file directly. Existing permission modes are retained, but ownership, ACLs, extended attributes, hard-link relationships, and crash durability are not guaranteed by this replacement scheme.
Documentation
- Installation Guide
- Configuration Guide
- Host Compatibility Matrix
- Acceptance & Test Matrix
- Release Guide
- Contributing
- Changelog
- Configuration Examples
Development
npm run typecheck # TypeScript type checking (tsc --noEmit)
npm test # Run Vitest suite
npm run check:release # Verify version sync, changelog, links, and package manifest
npm run verify # Run typecheck + test + check:release
License
MIT © 2026 ethan-blue