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
Workspace-wide shared-crate boundary and extraction-lane decisions are documented in
docs/specs/workspace-shared-crate-boundary-v1.md.
Workspace-level keep/delete ownership decisions are tracked in
docs/specs/workspace-doc-retention-matrix-v1.md.
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.
- GitHub adapters and
ghcommand orchestration (for example issue/PR write workflows).
Modules and purpose
env: truthy parsing helpers, env-presence checks,NO_COLORand prompt-segment color toggles, duration parsing, and trimmed non-empty env lookup.shell: POSIX single-quote escaping (with selectable escape style) and ANSI stripping modes.process: command execution wrappers (run_output/run_checked/run_stdout_trimmed/run_status_*), PATH lookup helpers, and headless browser-launch detection.git:gitcommand wrappers for repo probes,rev-parsehelpers, staged-path listing, name-status-z parsing, lockfile detection, and scope suggestion primitives for commit tooling.clipboard: best-effort clipboard copy with explicit tool priority.fs: atomic write, timestamp write/remove, UTF-8 text write, SHA-256 hashing, and cross-platform replace helpers with structured errors.markdown: markdown payload validation (with violation reporting), markdown-table-safe cell canonicalization, markdown heading/code-block rendering, and stable JSON pretty-format helpers used by orchestration/reporting CLIs.provider_runtime: provider-runtime substrate (paths, profiles, auth persistence, exec invocation, JSON/JWT helpers, structured errors) shared by Codex/Gemini-style CLIs without provider-specific UX copy.rate_limits_ansi: shared rate-limit table cell formatting (current-profile coloring and percent-band coloring) honoringNO_COLOR.
The crate also exposes a tiny top-level greeting(name: &str) -> String helper used by cli-template for the new-crate smoke test.
API examples
env:
use env;
let prompt_segment_enabled = env_truthy_or;
let no_color = no_color_enabled;
let maybe_agent_home = env_non_empty;
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
These mirror the workspace shared-crate-boundary spec
(docs/specs/workspace-shared-crate-boundary-v1.md) at the crate level:
- Moving provider-specific message wording, JSON envelope copy, or exit-code mapping into
nils-common. - Merging Codex and Gemini command-level UX into one behavior surface (parity-sensitive secret-dir routing stays crate-local until characterization proves a safe merge).
- Treating
nils-termas a generic runtime helper crate; progress bars, spinners, and TTY presentation policy stay innils-term. - Defining CLI-specific UX copy, warning templates, or emoji policy.
- Owning command-level business logic for a single CLI.
- Owning shared GitHub operation adapters such as
nils-common::github(keep crate-local adapters). - Hiding meaningful behavior differences that should remain explicit in local adapters.
- Keeping compatibility-only wrappers once shared helpers are canonical.
- Replacing specialized shared crates such as
api-testing-core,nils-term, ornils-test-support.