Arky is a Rust SDK for building AI agents. Cargo workspace with 14 crates under crates/.
- IF YOU DON'T CHECK SKILLS your task will be invalidated and we will generate rework
- YOU CAN ONLY finish a task after
make fmt && make lint && make testare ALL passing at 100%. No exceptions. - ALWAYS check dependent crate APIs before writing tests to avoid wrong code
- NEVER use workarounds, especially in tests - always use the
no-workaroundsskill for any fix/debug task +test-anti-patternsfor tests - ALWAYS use the
no-workaroundsandsystematic-debuggingskills when fixing bugs or complex issues - ALWAYS use
requirements-claritybefore implementing ambiguous multi-crate features or underspecified requests - USE
qa-test-plannerwhen defining regression scope or test strategy for significant changes - USE
adversarial-reviewbefore closing large or high-risk diffs that deserve a critical second pass
- MUST run
make fmt && make lint && make testbefore completing ANY subtask. All three commands must exit with zero errors and zero warnings. If any command fails, fix the issues and re-run until all pass. - ALWAYS USE the
rust-engineer+rust-best-practices+rust-coding-guidelinesskills for ALL Rust work - ALWAYS USE
rust-async-patternsskill when working with async code, tokio, channels, or streams - YOU SHOULD NEVER add dependencies by hand to Cargo.toml - always use
cargo addinstead - THIRDY PARTY LIBRARIES (just applied when needing external resources):
- MANDATORY Always use
sourcebotskill (5-7 times) to search code and find information about EXTERNAL libraries, frameworks, and code patterns - YOU MUST use Context7 (multiple times) when the library you research on
sourcebotis not available - NEVER use Sourcebot to search local project code. For local code, use
codebase_searchorGrep/Globinstead
- MANDATORY Always use
- ABSOLUTELY FORBIDDEN: NEVER run
git restore,git checkout,git reset,git clean,git rm,git push --force,git branch -D, or any other git commands that modify or discard working directory changes WITHOUT EXPLICIT USER PERMISSION. - DATA LOSS RISK: These commands can PERMANENTLY LOSE CODE CHANGES and cannot be easily recovered.
- REQUIRED ACTION: If you need to revert or discard changes, YOU MUST ASK THE USER FIRST and wait for explicit permission before executing any destructive git command.
- VIOLATION CONSEQUENCE: Running destructive git commands without explicit permission will result in IMMEDIATE TASK REJECTION and potential IRREVERSIBLE DATA LOSS.
- TOOL HIERARCHY: Use tools in this order:
codebase_search(if available) - Preferred semantic search toolGreporGlob(when exact string matching is needed)
- FORBIDDEN: Never use
greporfindvia Bash for semantic code discovery without first trying dedicated tools.
All commands run from repository root:
make fmt- Format Rust code (uses nightly for unstable rustfmt options)make fmt-check- Check Rust formatting without modifying filesmake lint- Run all lints (fmt check + clippy with-D warnings)make lint-clippy- Run clippy lints onlymake lint-fix- Auto-fix clippy warnings where possiblemake check- Type-check without producing binariesmake build- Build in release modemake test- Run all testsmake coverage- Print code coverage summarymake verify- Run fmt + lint + test (full verification)make clean- Clean build artifacts
MANDATORY Verification (BLOCKING): Before completing ANY task, you MUST run all three commands and they MUST all pass at 100%:
make fmt- Format all code. Must exit cleanly.make lint- Must pass with zero warnings and zero errors (includes fmt check + clippy with-D warnings).make test- All tests must pass with zero failures.
If any of these commands fail, the task is NOT complete. Fix all issues and re-run until all three pass.
- Edition: 2024
- Max line width: 90
- Imports granularity: Crate-level
- Format:
make fmt(nightly channel for unstable options). See.rustfmt.tomlfor full rules. - Lint:
make lint(clippy with-D warnings). See.clippy.tomlfor disallowed macros/methods. - Naming:
snake_case(fn/var),CamelCase(type),SCREAMING_SNAKE_CASE(const) - No
get_prefix: Usefn name()notfn get_name() - Conversions:
as_(cheap &),to_(expensive),into_(ownership) - Iterators:
iter()/iter_mut()/into_iter() - Newtypes: Use
struct Email(String)for domain semantics - Pre-allocate:
Vec::with_capacity(),String::with_capacity()
- Use
thiserrorfor all error types (library code) - Return
Result<T, E>for fallible operations; neverpanic!in library code - Never use
unwrap()in production code (useexpect()with messages in dev only) - Use
?operator for error propagation, notmatchchains - Each crate defines its own error enum implementing
ClassifiedErrorfromarky-error - Error codes follow pattern:
CRATE_ERROR_NAME(e.g.,PROVIDER_RATE_LIMITED,TOOL_TIMEOUT)
- All I/O-bound operations are async, using
tokioruntime CancellationTokenfromtokio-utilfor cooperative cancellation- Never hold locks across
.awaitpoints - Use
JoinSetfor managing multiple concurrent tasks - Sync for CPU-bound work; async is for I/O
- Keep traits small and focused (4-6 methods max)
- Use dynamic dispatch (
Box<dyn Trait>) for heterogeneous collections (tools, hooks) - Static dispatch for monomorphic paths
- All public traits must be
Send + Sync - Use
#[async_trait]for async trait methods
- Use
pretty_assertions::assert_eqinstead ofstd::assert_eq(enforced by clippy) - Name tests descriptively:
process_should_return_error_when_input_empty() - One assertion per test when possible
- Use
#[tokio::test]for async tests - Use doc tests (
///) for public API examples
//!for module-level docs///for public items//comments explain why (safety, workarounds, design rationale)- Every
TODOneeds a linked issue:// TODO(#42): ...
- No
logcrate: Usetracinginstead - No
todo!(),dbg!(),unimplemented!(): Do not commit these - No
std::assert_eq/std::assert_ne: Usepretty_assertionsversions - No
for_each/try_for_each: Useforloops for side-effects - No
map_or/map_or_else: Usemap(..).unwrap_or(..)for legibility
- Use Conventional Commits:
feat: ...,fix: ...,build: ...,refactor: ...,test: ...,docs: ... - Before opening a PR: run
make verify(fmt + lint + test) - PRs should include: clear description and linked issue
- Do not rewrite unrelated files or reformat whole repo - limit diffs to your change
arky/
Cargo.toml (workspace root)
crates/
arky/ facade crate, re-exports everything
arky-error/ shared error classification contracts
arky-core/ agent loop and orchestration
arky-provider/ Provider trait, ProviderRegistry
arky-claude-code/ Claude Code CLI wrapper provider
arky-codex/ Codex App Server wrapper provider
arky-tools/ Tool trait, ToolRegistry, ToolResult
arky-tools-macros/ #[tool] proc macro
arky-mcp/ MCP client, server, bidirectional bridge
arky-session/ SessionStore trait, InMemory, SQLite
arky-hooks/ Hooks trait, HookChain, ShellCommandHook
arky-config/ Configuration loading and validation
arky-protocol/ Shared types (Message, AgentEvent, etc.)
arky-server/ HTTP server for runtime exposure
- Leaf crates (no internal deps):
arky-error,arky-protocol,arky-config,arky-tools-macros - Foundation:
arky-tools,arky-hooks,arky-session,arky-provider - Integration:
arky-mcp - Providers:
arky-claude-code,arky-codex - Orchestration:
arky-core - Server:
arky-server - Facade:
arky
Every agent MUST follow this protocol before writing code:
- Core/Agent: agent loop, events, state ->
rust-engineer+rust-best-practices+rust-async-patterns - Provider: Provider trait, streaming, subprocess ->
rust-engineer+rust-async-patterns - Tools: Tool trait, registry, proc macro ->
rust-engineer+rust-coding-guidelines - Hooks: Hooks trait, lifecycle events ->
rust-engineer+rust-async-patterns - Session: SessionStore, persistence ->
rust-engineer+rust-best-practices - MCP: MCP client/server, bridge ->
rust-engineer+rust-async-patterns - Config: Configuration loading ->
rust-engineer+rust-coding-guidelines - Protocol: Shared types, serialization ->
rust-engineer+rust-coding-guidelines - Server: HTTP server, axum ->
rust-engineer+rust-async-patterns - Bug fix: any domain ->
systematic-debugging+no-workarounds+ domain skills - Tests: any domain ->
test-anti-patterns+ domain skills - Ambiguous requirements / multi-crate scope ->
requirements-clarity - Test plan / regression scope ->
qa-test-planner+test-anti-patterns - Large or high-risk diff review ->
adversarial-review - External lib research ->
sourcebot+deep-research - Skill discovery / capability gaps ->
find-skills
| Domain | Required Skills | Conditional Skills |
|---|---|---|
| Any Rust code | rust-engineer + rust-best-practices |
+ rust-coding-guidelines (style/naming) |
| Async code | rust-async-patterns |
+ rust-engineer |
| Bug fix | systematic-debugging + no-workarounds |
+ test-anti-patterns (test failures) |
| Writing tests | test-anti-patterns |
+ domain skill for code being tested |
| Ambiguous requirements | requirements-clarity |
+ domain skills after scope is clear |
| Test planning / regression design | qa-test-planner |
+ test-anti-patterns |
| High-risk change review | adversarial-review |
+ receiving-code-review (follow-up feedback) |
| External lib research | sourcebot |
+ deep-research (complex analysis) |
| Task completion | verification-before-completion |
|
| Code review response | receiving-code-review |
|
| Git rebase/conflicts | git-rebase |
|
| Architecture audit | architectural-analysis |
+ adversarial-review (for risky structural changes) |
| Skill discovery / workflow extension | find-skills |
|
| Parallel agent work | dispatching-parallel-agents |
Before any agent marks a task as complete:
- Activate
verification-before-completionskill - Run
make fmt && make lint && make test- all three must pass at 100% with zero errors and zero warnings - Read and verify the full output - no skipping
- Only then claim completion
NEVER do these:
- Skip skill activation because "it's a small change" - every domain change requires its skill
- Activate only one skill when the task touches multiple domains
- Forget
verification-before-completionbefore marking tasks done - Use
sourcebotfor local code - it's only for external libraries - Write tests without
test-anti-patterns- leads to bad test patterns - Fix bugs without
systematic-debugging- leads to symptom-patching - Apply workarounds without
no-workarounds- type assertions, lint suppressions, error swallowing are all rejected - Start implementation with unclear scope and skip
requirements-clarity- this creates avoidable rework - Skip
qa-test-plannerwhen designing meaningful regression coverage - this weakens validation quality - Ship large or risky diffs without
adversarial-review- this misses obvious failure modes - Complete tasks without running
make fmt && make lint && make test- all three must pass. Skipping any invalidates the task. - Claim task is done when any check has warnings or errors - zero warnings, zero errors, zero test failures. No exceptions.
- Use
unwrap()in library code - always use?orexpect()with a message - Use
logcrate - usetracinginstead (enforced by clippy) - Commit
todo!(),dbg!(), orunimplemented!()- enforced by clippy
The full technical specification is at ../compozy-code/tasks/prd-rust-providers/techspec.md. ADR documents are at ../compozy-code/tasks/prd-rust-providers/adrs/.