nils-common
nils-common is the workspace shared helper crate for cross-CLI primitives.
Primary constraint: shared helpers must preserve behavioral parity for each consuming CLI. Moving logic into this crate must not change user-facing output text, warnings, color behavior, or exit-code contracts.
Shared helper policy
What belongs in nils-common
- Reusable helper logic used by multiple CLI crates.
- Domain-neutral primitives (process/env/shell/git/clipboard/fs internals).
- APIs that return structured results and let callers own final UX text.
- Behavior that can be covered by deterministic unit tests.
What stays crate-local
- User-facing warning/error text (including emoji/prefix wording).
- Exit-code mapping and command-level failure policy.
- CLI-specific command composition and UX defaults.
- Product/business/domain flows that only make sense in one crate.
Modules and purpose
env: truthy parsing helpers andNO_COLORpresence checks.shell: POSIX single-quote escaping and ANSI stripping modes.process: command execution wrappers plus PATH lookup helpers.git:gitcommand wrappers for repo probes andrev-parsehelpers.clipboard: best-effort clipboard copy with explicit tool priority.fs: atomic write, timestamp write/remove, SHA-256 hashing, and cross-platform replace helpers with structured errors.greeting: tiny sample helper used bycli-template.
API examples
env:
use env;
let starship_enabled = env_truthy_or;
let no_color = no_color_enabled;
println!;
shell:
use ;
let quoted = quote_posix_single_with_style;
let plain = strip_ansi;
assert_eq!;
assert_eq!;
process:
use process;
assert!;
let git_path = find_in_path.expect;
let out = run_stdout_trimmed
.expect;
println!;
git:
use git;
let inside = is_inside_work_tree.expect;
if inside
clipboard:
use ;
let tool_order = ;
let outcome = copy_best_effort;
if matches!
fs:
use ;
use Path;
write_atomic?;
write_timestamp?;
let digest = sha256_file?;
if let Err =
write_atomic
println!;
# Ok::
Migration conventions for parity
When introducing a shared helper at a call site:
- Add or keep characterization tests in the caller crate first.
- Move only primitive logic; keep a crate-local adapter for message formatting and exit-code mapping.
For
write_atomic/write_timestamp/sha256_filemigrations, map structured errors back to existing crate-local UX text. - Preserve existing quote/ANSI mode choices and
NO_COLORbehavior. - Keep tool/command fallback order identical (for example clipboard tool order, git probe fallback behavior).
- Re-run crate tests that cover the touched command paths before merging.
Non-goals
- Defining CLI-specific UX copy, warning templates, or emoji policy.
- Owning command-level business logic for a single CLI.
- Hiding meaningful behavior differences that should remain explicit in local adapters.
- Replacing specialized shared crates such as
api-testing-core,nils-term, ornils-test-support.