rust-cli-agent-style
OpenAI Codex Rust CLI Agent Best Practices
This skill teaches you to write Rust code in the style of the OpenAI Codex codebase - a production CLI/agent system with 50 crates and 787 Rust files.
Key Characteristics
- Edition 2024 with strict Clippy configuration
- Zero unwrap/expect in non-test code (enforced at workspace level)
- Tokio async runtime with proper Send + Sync bounds
- thiserror for library errors, anyhow for application code
- Flat workspace structure with centralized dependencies
When to Apply
Apply this skill when:
- Building CLI tools or agent systems in Rust
- Writing async Rust with Tokio
- Designing Rust workspace organization
- Implementing error handling patterns
- Working on production Rust codebases
Quick Reference
Critical Rules (Must Follow)
| Rule | Description |
|---|---|
| err-no-unwrap | Never use unwrap() in non-test code |
| err-no-expect | Avoid expect() in library code |
| err-thiserror-domain | Use thiserror for domain errors |
| err-context-chain | Add context to errors with .context() |
Error Handling
| Rule | Description |
|---|---|
| err-anyhow-application | Use anyhow::Result for entry points |
| err-from-derive | Use #[from] for error conversion |
| err-transparent | Use #[error(transparent)] for wrapped errors |
| err-structured-variants | Include relevant data in error variants |
| err-io-result | Use std::io::Result for I/O functions |
| err-map-err-conversion | Use map_err for error conversion |
| err-doc-errors | Document error conditions |
Organization
| Rule | Description |
|---|---|
| org-workspace-flat | Flat workspace with utils subdirectory |
| org-crate-naming | kebab-case directories, project prefix |
| org-module-visibility | Use pub(crate) for internal APIs |
| org-test-common-crate | Shared test utilities crate |
| org-integration-tests-suite | Tests in suite directory |
| org-feature-modules | Feature-based module organization |
| org-handlers-subdir | Handlers in dedicated subdirectory |
| org-errors-file | Errors in dedicated file |
Component Patterns
| Rule | Description |
|---|---|
| mod-derive-order | Consistent derive macro ordering |
| mod-async-trait-macro | Use #[async_trait] for async traits |
| mod-trait-bounds | Send + Sync + 'static for concurrent traits |
| mod-extension-trait-suffix | Ext suffix for extension traits |
| mod-builder-pattern | Builder pattern for complex config |
| mod-type-alias-complex | Type aliases for complex generics |
| mod-impl-block-order | Consistent impl block ordering |
| mod-generic-constraints | Where clauses for complex bounds |
| mod-newtype-pattern | Newtypes for type safety |
| mod-struct-visibility | Private fields with public constructor |
| mod-serde-rename | Serde rename for wire format |
| mod-jsonschema-derive | JsonSchema for API types |
Naming Conventions
| Rule | Description |
|---|---|
| name-async-no-suffix | No _async suffix for async functions |
| name-try-prefix-fallible | try_ prefix for fallible constructors |
| name-with-prefix-builder | with_ prefix for builder methods |
| name-handler-suffix | Handler suffix for handlers |
| name-error-suffix | Error suffix for error types |
| name-result-type-alias | Crate-specific Result alias |
| name-const-env-var | _ENV_VAR suffix for env constants |
| name-request-response | Request/Response type pairing |
| name-options-suffix | Options suffix for config bundles |
| name-info-suffix | Info suffix for read-only data |
| name-provider-suffix | Provider suffix for services |
| name-client-suffix | Client suffix for API clients |
| name-manager-suffix | Manager suffix for lifecycle mgmt |
| name-bool-is-prefix | is_/has_/should_ for booleans |
| name-plural-collections | Plural names for collections |
Style
| Rule | Description |
|---|---|
| style-import-granularity | One item per use statement |
| style-deny-stdout | Deny stdout/stderr in libraries |
| style-inline-format-args | Inline format arguments |
| style-module-docs | Module-level documentation |
| style-expect-reason | #[expect] with reason for lints |
| style-cfg-test-module | Unit tests in mod tests |
Cross-Crate
| Rule | Description |
|---|---|
| cross-workspace-lints | Workspace-level lint config |
| cross-workspace-deps | Centralized dependency versions |
Example: Proper Error Handling
use thiserror::Error;
use anyhow::Context;
// Domain error with thiserror
#[derive(Debug, Error)]
pub enum ConfigError {
#[error("failed to read config file: {path}")]
ReadFailed {
path: PathBuf,
#[source]
source: std::io::Error,
},
#[error(transparent)]
Parse(#[from] toml::de::Error),
}
// Library function returns domain error
pub fn load_config(path: &Path) -> Result<Config, ConfigError> {
let content = fs::read_to_string(path)
.map_err(|source| ConfigError::ReadFailed {
path: path.to_owned(),
source,
})?;
toml::from_str(&content).map_err(Into::into)
}
// Application code uses anyhow with context
fn main() -> anyhow::Result<()> {
let config = load_config(Path::new("config.toml"))
.context("failed to load configuration")?;
run(config).await
}
Source
Patterns extracted from OpenAI Codex (codex-rs/ subdirectory) - a production Rust codebase with 50 crates and 787 Rust files.
More from pproenca/dot-skills
zod
Zod schema validation best practices for type safety, parsing, and error handling. This skill should be used when defining z.object schemas, using z.string validations, safeParse, or z.infer. This skill does NOT cover React Hook Form integration patterns (use react-hook-form skill) or OpenAPI client generation (use orval skill).
2.0Kclean-architecture
Clean Architecture principles and best practices from Robert C. Martin's book. This skill should be used when designing software systems, reviewing code structure, or refactoring applications to achieve better separation of concerns. Triggers on tasks involving layers, boundaries, dependency direction, entities, use cases, or system architecture.
1.4Kemilkowal-animations
Emil Kowalski's animation best practices for web interfaces. Use when writing, reviewing, or implementing animations in React, CSS, or Framer Motion. Triggers on tasks involving transitions, easing, gestures, toasts, drawers, or motion.
918vitest
Vitest testing framework patterns for test setup, async testing, mocking with vi.*, snapshots, and test performance (formerly test-vitest). This skill should be used when writing or debugging Vitest tests. This skill does NOT cover TDD methodology (use test-tdd skill), API mocking with MSW (use test-msw skill), or Jest-specific APIs.
907typescript
This skill should be used when the user asks to "optimize TypeScript performance", "speed up tsc compilation", "configure tsconfig.json", "fix type errors", "improve async patterns", or encounters TS errors (TS2322, TS2339, "is not assignable to"). Also triggers on .ts, .tsx, .d.ts file work involving type definitions, module organization, or memory management. Does NOT cover TypeScript basics, framework-specific patterns, or testing.
821nuqs
nuqs (type-safe URL query state) best practices for Next.js applications. This skill should be used when writing, reviewing, or refactoring code that uses nuqs for URL state management. Triggers on tasks involving useQueryState, useQueryStates, search params, URL state, query parameters, nuqs parsers, or Next.js routing with state.
735