Skip to main content

oy/
lib.rs

1//! # oy
2//!
3//! `oy` prepares deterministic repository evidence for audits and code-quality reviews, and
4//! finalizes the resulting Markdown/SARIF reports. The review, audit, and one-finding-fix
5//! workflows run as [Agent Skills](https://agentskills.io/) inside whichever agent the user
6//! prefers — OpenCode, Cursor, Codex, Copilot, or Gemini CLI all discover skills under
7//! `.agents/skills`. `oy setup` installs the skills; the agent executes them under its own
8//! permission model. oy does not store provider credentials.
9//! The native CLI supports Linux and macOS; Windows users should run it in WSL2.
10//!
11//! ## Start with the CLI
12//!
13//! The command-line interface is the supported automation surface:
14//!
15//! ```text
16//! oy setup                    # install the oy skills under ~/.agents/skills
17//! oy setup --workspace        # install project-local skills under .agents/skills
18//! oy audit prepare --path .   # prepare deterministic audit evidence
19//! oy audit finalize --run <id># write ISSUES.md or SARIF
20//! oy review prepare main      # prepare a git-diff review
21//! oy review finalize --run <id># write REVIEW.md
22//! oy doctor --check           # verify the skills installation
23//! ```
24//!
25//! See the [getting-started guide](https://oy.adonm.dev/getting-started.html),
26//! [workflow guide](https://oy.adonm.dev/workflows.html), and
27//! [CLI reference](https://oy.adonm.dev/reference.html) for the user-facing contract.
28//!
29//! ## Determinism boundary
30//!
31//! Input collection, ordering, limits, and report rendering are deterministic. Findings are
32//! produced by the model the user's agent runs and are not deterministic. The collector also
33//! has documented exclusions; “all chunks” does not mean every byte in a repository.
34//!
35//! ## Rust API
36//!
37//! This crate exists primarily to keep the `oy` binary entrypoint small. [`run`] and
38//! [`err_line`] are public for that entrypoint and lightweight embedding, but spawning the
39//! `oy` executable is preferred for automation. Other modules and implementation details are
40//! private and may change without a semver-stable library API commitment.
41//!
42//! ```no_run
43//! # fn example() -> anyhow::Result<()> {
44//! // Arguments exclude the executable name, just like std::env::args().skip(1).
45//! let exit_code = oy::run(vec!["doctor".into(), "--json".into()])?;
46//! assert_eq!(exit_code, 0);
47//! # Ok(())
48//! # }
49//! ```
50
51#![recursion_limit = "256"]
52
53mod artifacts;
54mod audit;
55mod cli;
56mod review;
57mod skills;
58mod tools;
59mod workflow;
60
61pub(crate) use cli::{config, ui};
62
63#[derive(Debug, Clone, Copy, PartialEq, Eq)]
64pub(crate) enum TextDecodeError {
65    Binary,
66    NonUtf8,
67}
68
69pub(crate) fn decode_utf8(raw: Vec<u8>) -> Result<String, TextDecodeError> {
70    if raw.contains(&0) {
71        return Err(TextDecodeError::Binary);
72    }
73    String::from_utf8(raw).map_err(|_| TextDecodeError::NonUtf8)
74}
75
76/// Runs the `oy` command dispatcher with arguments that exclude the executable name.
77///
78/// Normal command statuses are returned as `Ok(code)`. Setup, filesystem, and process
79/// failures are returned as errors. This function may update the agent skills installation
80/// or launch child processes depending on the arguments.
81///
82/// Prefer invoking the `oy` executable when process isolation or concurrent invocations
83/// matter; CLI output configuration is process-global.
84pub fn run(argv: Vec<String>) -> anyhow::Result<i32> {
85    cli::app::run(argv)
86}
87
88/// Writes a formatted diagnostic line to standard error.
89///
90/// This is primarily exposed for the binary entrypoint.
91///
92/// ```
93/// oy::err_line(format_args!("error: {}", "example"));
94/// ```
95pub fn err_line(args: std::fmt::Arguments<'_>) {
96    ui::err_line(args);
97}