aru
aru keeps coding-agent instructions, Agent Skills, and MCP servers consistent across a project.
[!WARNING] Work in progress:
aruis under active development. Features, behavior, and file formats may change without notice.
Declare what your project needs in aru.toml, pin the exact result in aru.lock, then use aru sync to safely reconcile each agent's project files.
Read the documentation · View the source
✨ At a glance
| Resource | Source of truth | Target result |
|---|---|---|
| Native packages | Git repositories with a package-mode aru.toml |
Composed instructions, skills, trusted MCP, and package dependencies |
| Instructions | Existing AGENTS.md files or configured Markdown sources |
Native use, Claude imports/rules, or Copilot instructions |
| Agent Skills | Git repositories | Native project skill directories for every supported target |
| MCP servers | Registry packages, HTTPS endpoints, or stdio argv | Codex, Claude, Copilot CLI, and OpenCode MCP configuration |
Aru is designed to be reproducible and fail closed: it validates the complete operation before writing, does not execute configured MCP commands, and preserves drifted or unowned content for review.
🧭 Contents
- Install
- Quick start
- Manage native packages
- Manage instructions
- Manage skills
- Manage MCP servers
- Manage targets
- Lock and sync
- Inspect packages and metadata
- Audit project integrity
- Export locked inventory
- Project files
- Target capabilities
- Safety and recovery
- Offline demo
- Development
📦 Install
You need a system git executable to use aru.
Install the PyPI distribution with uv:
uv tool install arust
The PyPI distribution is named arust because aru was already taken, but it installs and runs the aru command.
Update this installation with uv tool upgrade arust.
Prebuilt wheels support x86-64 glibc Linux, Intel and Apple Silicon macOS, and x86-64 Windows.
The standalone installers download a prebuilt, checksum-verified binary and do not require Rust.
On macOS or Linux, install the latest release into ~/.local/bin/aru with either curl or wget:
curl -LsSf https://raw.githubusercontent.com/narumiruna/aru/main/install.sh | sh
wget -qO- https://raw.githubusercontent.com/narumiruna/aru/main/install.sh | sh
On 64-bit Windows, install into ~/.local/bin/aru.exe with Windows PowerShell:
powershell -ExecutionPolicy ByPass -c "irm https://raw.githubusercontent.com/narumiruna/aru/main/install.ps1 | iex"
The installers currently support x86-64 Linux, Intel and Apple Silicon macOS, and x86-64 Windows. Set ARU_VERSION to install a specific stable version or ARU_INSTALL_DIR to choose another directory. If the destination is not already on PATH, the installer prints the path to add.
Alternatively, install the latest release from crates.io with a Rust toolchain:
cargo install aru
Or install from a source checkout:
cargo install --path .
Verify the installation:
aru --help
Self-update
Binaries installed by the standalone curl, wget, or PowerShell installers can update themselves to the latest stable GitHub Release without an aru.toml project:
aru self update
Download and checksum-verify the complete update without replacing the current executable:
aru self update --dry-run
Self-update is disabled for uv- and Cargo-managed binaries so aru does not overwrite package-manager-owned files.
Update those installations with uv tool upgrade arust or cargo install aru --locked instead.
--offline and --frozen reject self-update before network access.
Shell completions
Generate a completion script from the current command tree and install it in your shell's user completion directory:
Bash (requires bash-completion):
mkdir -p ~/.local/share/bash-completion/completions
aru generate-shell-completion bash > ~/.local/share/bash-completion/completions/aru
Zsh:
mkdir -p ~/.zfunc
aru generate-shell-completion zsh > ~/.zfunc/_aru
Add fpath=(~/.zfunc $fpath) to .zshrc before autoload -Uz compinit && compinit.
Fish:
mkdir -p ~/.config/fish/completions
aru generate-shell-completion fish > ~/.config/fish/completions/aru.fish
The command writes only the script to stdout and does not require an aru.toml project.
Aru passes Git arguments directly and uses your existing SSH or credential-helper configuration. It never invokes a shell for Git operations.
🚀 Quick start
1. Initialize a project
Initialize the current directory, or pass another existing directory as PATH:
aru init --target codex --target claude --target copilot
aru init PATH --target codex
This creates the project manifest and configures the initial target set.
Supported target names are agents, codex, claude, copilot, pi, and opencode.
2. Adopt existing instructions
Preview discovery before changing project files:
aru instruction add --discover --dry-run
Then apply it:
aru instruction add --discover
[!IMPORTANT] Before 1.0,
aru instruction initwas replaced directly byaru instruction add --discover; there is no compatibility alias.
If an unmanaged CLAUDE.md or .github/copilot-instructions.md already exists, aru reports a collision. Choose one explicit strategy:
aru instruction add --discover --merge # preserve Markdown and add owned blocks
aru instruction add --discover --force # replace unmanaged instruction output
[!CAUTION]
--forceis destructive takeover. Use it only when aru should replace the colliding unmanaged key or path. A later remove will not restore the old content.
3. Add a skill
aru skill add narumiruna/skills
In an interactive terminal, aru opens a searchable multi-select menu:
| Input | Action |
|---|---|
| Type | Filter the list |
| ↑ / ↓ | Move through results |
| Space | Toggle an item |
| → / ← | Select all / none |
| Enter | Confirm |
| Esc | Cancel without changing project files |
Verify that the committed lock can be replayed, then check local synchronization without writing:
aru sync --locked
aru sync --check
You now have:
aru.toml— human-maintained project intentaru.lock— exact, reproducible resolutions and projections- Target files — reconciled instructions, skills, and MCP configuration
📦 Manage native packages
A native aru package is a Git repository with a root aru.toml containing [package] metadata. It can export embedded instructions, skills, trusted MCP declarations, and bounded transitive package dependencies.
aru add owner/agent-kit
aru add owner/agent-kit --version '^1.2'
aru add ../local-agent-kit --target codex --target claude
aru add owner/mcp-kit --trust-mcp docs
add updates aru.toml, resolves the complete package graph into aru.lock, and synchronizes projections by default. Use --no-sync to defer target paths or --dry-run to use temporary storage and write nothing. Package instructions that need to join an existing unmanaged AGENTS.md require explicit --merge; --force remains destructive takeover.
Compatible lock nodes remain pinned during ordinary sync. Preview or apply updates with Cargo-style selection:
aru update --dry-run
aru update
aru update owner/agent-kit
aru update owner/agent-kit --precise 1.2.3
aru remove owner/agent-kit
Package-provided MCP servers are denied by default. --trust-mcp NAME records a root, credential-free decision for that package source; it never bypasses transport, target, secret, or ownership validation. Transitive local paths, scripts, hooks, duplicate exports, cycles, conflicting source requirements, unsupported targets, and oversized graphs fail before project writes.
Package authors can validate inventory and build a deterministic archive from a clean package Git root:
aru package --list
aru package
aru package --output dist/agent-kit.tar.gz
aru package --allow-dirty
package validates the current package-mode aru.toml, archive paths/content, and dependency graph before writing. It includes tracked and non-ignored files, rejects symlinks/special files/case collisions/hidden controls, and normalizes tar ordering, timestamps, ownership, and permissions. Dirty input requires explicit --allow-dirty; .aru/, ignored files, and target/aru-package/ are excluded.
See the complete aru.toml package, graph, trust, and archive contracts.
📝 Manage instructions
Existing AGENTS.md files remain canonical and user-owned. Aru records their paths without moving, editing, or removing them.
Configure instruction sources in aru.toml:
[[instructions.sources]]
files = ["AGENTS.md", "src/**/AGENTS.md"]
exclude = ["target/**", "third_party/**"]
scope = "source-directory"
[[instructions.sources]]
files = ["docs/instructions/rust.md"]
apply-to = ["**/*.rs"]
targets = ["claude", "copilot"]
Each source uses exactly one scoping model:
scope = "source-directory"requires matched files namedAGENTS.md. Each file applies to its own directory tree.apply-todeclares exact, repository-relative globs for targets that can preserve path-specific rules.
The optional targets list defaults to all project targets and must be a subset of them. All patterns are project-relative; .git/** and .aru/** are always excluded.
Aru projects instructions according to target capabilities:
- Codex, pi, and OpenCode consume directory-scoped
AGENTS.mdfiles directly, so aru does not duplicate them. - Claude Code receives sibling
CLAUDE.mdimport blocks and path rules under.claude/rules/aru/. - GitHub Copilot receives a root
.github/copilot-instructions.mdblock and path-specific files under.github/instructions/aru/.
Unsupported scope and target combinations fail before any write. Removing a source or target removes only digest-matching, aru-owned output; drifted or unowned content is preserved for review.
List declared file selectors or remove exact selectors without touching canonical source files:
aru instruction list
aru instruction remove AGENTS.md --dry-run
aru instruction remove AGENTS.md
Use --no-sync on add or remove to update only aru.toml and aru.lock; aru reports that target paths remain pending.
🧩 Manage skills
Select exports
Use one selection mode per skill add command:
aru skill add owner/repository # interactive selection
aru skill add owner/repository --all # every current and future export
aru skill add owner/repository -a # short form of --all
aru skill add owner/repository --skill review \
--skill applying-tdd # explicit, repeatable names
aru skill add owner/repository --path extras/review # non-standard layout
aru skill add owner/repository --all --target codex # narrow deployment
In a pipe, redirected shell, or CI runner, a bare skill add fails before fetching. Pass --all, --skill, or --path explicitly. At least one skill must be selected.
Selection behavior is deliberate:
--allstores wildcard intent and tracks valid exports added by future versions.- Interactive selection stores an explicit snapshot, even when every visible export is selected.
- Reopening a wildcard preserves it when all exports remain selected; deselecting one converts it to an explicit snapshot.
- Repeated
--skillselections are additive. - Removing the final explicit skill removes the package.
- A
--pathselection remains inaru.tomluntil explicitly removed.
Pin a source revision
aru skill add owner/repository --version 0.5.0
aru skill add owner/repository --version '=0.5.0'
aru skill add owner/repository --branch main
aru skill add ssh://git@example.com/team/skills.git \
--rev 67cd354 --skill review
| Option | Resolution behavior |
|---|---|
| No reference option | Latest matching SemVer tag; falls back to main when none exists |
--version 0.5.0 |
Cargo caret semantics: ^0.5.0 |
--version '=0.5.0' |
Exact tag |
--branch main |
Current branch head, pinned to an exact commit in aru.lock |
--rev <SHA> |
Immutable 7–40 character commit |
--version, --branch, and --rev are mutually exclusive.
Source arguments contain neither a path selector nor a reference, so SCP-like git@host:path sources remain unambiguous.
Equivalent canonical Git sources do not create duplicate packages.
The main fallback applies only when no reference option is provided; an explicit --version remains strict.
The fallback commit is pinned in aru.lock, and a later update prefers a matching SemVer tag if the repository adds one.
Use --upgrade / -U during add to re-resolve an existing source instead of reusing its lock:
aru skill add owner/repository --skill review --upgrade
A new source installs normally. An existing SemVer source selects the latest matching tag, a branch selects its current head, and an exact revision remains fixed.
Update or remove
aru skill list
aru skill update --dry-run # preview current and candidate revisions
aru skill update # update all eligible sources
aru skill update owner/repository # update one source
aru skill remove owner/repository --skill review
aru skill remove owner/repository # remove the source
skill list writes deterministic tab-separated name, locked version, and canonical source records to stdout. Repeat --target to narrow a skill source to configured, skill-capable targets. Omit it to use every compatible project target.
Skills project to each target's native project directory: .agents/skills/ for Agents and Codex, .claude/skills/ for Claude, .github/skills/ for Copilot, .pi/skills/ for pi, and .opencode/skills/ for OpenCode.
When Agents or Codex receives the same skill, aru creates one canonical .agents copy.
On Unix, other native paths link to that copy; platforms without project symlinks receive verified copies.
Ordinary aru sync and aru sync --locked keep a branch's locked commit. Run skill update or add with --upgrade to move it. Because force-pushes can make old commits unreachable, prefer immutable SemVer tags for published, long-lived configurations.
🔌 Manage MCP servers
Aru accepts three MCP source types.
Registry package
aru mcp add io.example/context \
--name context \
--transport stdio \
--package-registry npm
Registry packages support npm records rendered through exact npx argv and PyPI records that explicitly declare the uvx runtime hint. Select PyPI with --package-registry pypi. A Registry candidate must be unique after transport, package-registry, and configured-target capability filtering; aru never chooses the first API result when multiple candidates remain. Cargo, OCI, NuGet, MCPB, unknown runtime hints, secret arguments, and unresolved required arguments remain fail-closed. Use a pinned direct stdio declaration when you need an argv shape the Registry cannot represent safely.
Direct HTTPS endpoint
aru mcp add \
--url https://docs.example.com/mcp \
--name docs \
--bearer-token-env DOCS_MCP_TOKEN \
--header-env X-Workspace=DOCS_MCP_WORKSPACE
Repeat --header-env HEADER=ENV for non-Authorization headers whose values come from the environment. Header names are case-insensitive and cannot collide; use --bearer-token-env rather than a second Authorization declaration. Aru stores only each environment variable name or target placeholder, never its value. Repeat --target to narrow any MCP declaration to configured MCP-capable targets:
aru mcp add \
--url https://docs.example.com/mcp \
--name docs \
--target claude
Direct stdio command
aru mcp add \
--command uvx \
--arg=--with \
--arg 'mcp<2' \
--arg yfmcp@0.12.2 \
--env-var YFINANCE_API_KEY \
--name yfinance
Repeat --env-var NAME to forward an existing environment variable without reading it. Aru stores the executable and each repeated --arg as an ordered argv array. Use --arg=--flag when an argument begins with -. Aru projects these commands but never executes them during add, lock, or sync.
Pin package versions explicitly in argv. The example constrains the unbounded MCP SDK dependency because yfmcp 0.12.2 uses the 1.x API.
Update or remove servers by project-local name:
aru mcp list
aru mcp update --dry-run
aru mcp update context
aru mcp remove docs
mcp list writes deterministic tab-separated name, source type, and transport records to stdout. mcp update [name] unlocks only selected Registry packages. Direct URLs and direct stdio commands do not have Registry versions to upgrade.
Project MCP is supported for Codex, Claude, Copilot CLI, and OpenCode.
Agents and pi have no built-in MCP and are rejected as MCP dependency targets.
Copilot uses the shared repository file .github/mcp.json; aru does not emit VS Code's incompatible .vscode/mcp.json or modify GitHub.com repository settings.
OpenCode's opencode.json is edited as JSONC so unrelated settings, comments, and formatting survive.
🎯 Manage targets
Targets are the coding-agent project layouts that aru reconciles.
Supported target names are agents, codex, claude, copilot, pi, and opencode.
aru target list
aru target add claude
aru target remove codex
aru target set codex claude
addperforms a set union.removeperforms a set subtraction.setreplaces the complete set atomically.- Repeating an already configured target is safe.
- Unknown targets and unconfigured removal arguments fail before writes.
At least one target must remain. To switch a Codex-only project to Claude, run aru target set claude instead of trying to remove the only target first.
Target mutations resolve the complete result before atomically updating aru.toml, aru.lock, ownership state, and owned project paths. They preserve locked package versions and support --dry-run. target add and target set also support --merge and --force for new-target instruction collisions.
Use --no-sync to update only manifest and lock intent, then run aru sync later. If local ownership state is missing and deferral would lose information required for a Claude copy/symlink conversion, aru rejects --no-sync and asks you to apply the change directly.
🔒 Lock and sync
| Command | Behavior |
|---|---|
aru lock |
Resolve instructions and packages; update aru.lock without changing target paths |
aru lock --check |
Check that the existing lock is complete and current without writing or using the network |
aru sync |
Reuse compatible locked packages, fill missing lock data, and reconcile target paths |
aru sync --locked |
Require a complete, current lock; never change it or advance a branch |
aru sync --check |
Check the lock and all target paths locally without writing |
aru sync --dry-run |
Print the deterministic plan without changing persistent project state |
--dry-run / -n may read Git or HTTP sources through temporary storage. It does not modify aru.toml, aru.lock, .aru/, or target paths.
--no-sync on add, remove, or update still resolves and transactionally updates aru.toml and aru.lock; it skips only target projections and prints the command needed to apply them later.
Common uv/Cargo-style options
| Option | Behavior |
|---|---|
--project <PATH> |
Discover the aru project from a specific directory |
--locked |
Fail if the command would change aru.lock |
--offline |
Disable remote Git and Registry access; use local sources or cached locks |
--frozen |
Equivalent to --locked --offline |
-q, --quiet |
Suppress normal status output, but keep errors and actionable warnings |
-v, --verbose |
Show resolved revisions and digests; repeat for projection identity detail |
--color auto|always|never |
Control color in human-readable status output |
--no-progress |
Hide static TTY resolution progress |
Aru sends list data to stdout and human-readable status to stderr. Normal status uses Cargo-style verbs and omits full digests:
Locked skill review 1.2.0
Created skill review (.agents/skills/review)
Updated aru.toml
Updated aru.lock
Finished Project synchronized.
Use -v when exact revisions and digests are needed. Status meaning never depends on color.
Changing project.targets by hand does not unlock package versions, but it invalidates the projection hash. A locked sync will fail until a normal sync updates per-target projections. Prefer aru target add, remove, or set so all related state changes in one transaction.
🌳 Inspect packages and metadata
Inspection commands read validated lock evidence and write no project state:
aru tree
aru tree --depth 2 --target claude
aru tree --invert shared-rules
aru tree --format json
aru info agent-kit
aru metadata --format-version 1
aru metadata --format-version 1 --no-deps
tree renders a deterministic deduplicated package graph; --invert shows reverse dependencies. info uses exact locked evidence when installed and can inspect an undeclared Git package through bounded temporary storage. metadata requires an explicit contract version, emits JSON only to stdout, removes URL credentials, and never fetches; --no-deps limits package records to direct graph roots.
🔍 Audit project integrity
Run a detailed, local integrity review without changing project or cache state:
aru audit
aru audit --format json
aru audit --format json --output audit.json
Audit checks manifest and lock consistency, pending recovery, ownership references, target projection drift, deployed skill content, and hidden Unicode format controls in instructions and deployed skills. Ordinary multilingual text and emoji are accepted. Bidi controls, zero-width format controls, and unexpected byte-order marks are blocking findings with exact path, line, column, and code point.
aru sync --check remains the concise exact-state gate. aru audit provides versioned, sorted findings and remediation guidance. It is non-interactive, uses no network, never repairs state, and exits non-zero when blocking findings exist. JSON schema version 1 is written to stdout unless --output is explicit; human findings and status use stderr.
📤 Export locked inventory
Export the existing lock as a deterministic CycloneDX 1.5 inventory:
aru export --format cyclonedx1.5
aru export --format cyclonedx1.5 --output-file sbom.json
aru export --format cyclonedx1.5 --timestamp 2026-07-31T00:00:00Z
Export reads and validates aru.lock only. It performs no resolution, source fetch, source rehash, ownership update, or target write. Components and relationships are sorted, URL credentials are removed, and unknown or invalid URLs fail rather than produce a partial inventory. Omit --timestamp for timestamp-free deterministic output, or provide an RFC 3339 UTC value for byte-stable metadata.
The result is a dependency inventory, not a vulnerability, license, provenance, or security attestation. SPDX is not part of the first export contract.
📂 Project files
| Path | Commit? | Purpose |
|---|---|---|
aru.toml |
Yes | Human-maintained sources, package requirements, selectors, and targets |
aru.lock |
Yes | Exact Git commits, MCP metadata, source digests, projections, and portable ownership baseline |
AGENTS.md, **/AGENTS.md |
Yes | User-owned, directory-scoped instruction sources |
CLAUDE.md, **/CLAUDE.md |
Optional | Claude imports managed as source-specific marker blocks |
.claude/rules/aru/** |
Optional | Aru-owned Claude path-specific instruction projections |
.github/copilot-instructions.md |
Optional | Copilot root instructions with source-specific marker blocks |
.github/instructions/aru/** |
Optional | Aru-owned Copilot path-specific instruction projections |
.agents/skills/<name> |
Optional | Agents and Codex project skill projection |
.claude/skills/<name> |
Optional | Claude skill link to .agents, when possible, or a verified copy |
.github/skills/<name> |
Optional | Copilot skill link to .agents, when possible, or a verified copy |
.pi/skills/<name> |
Optional | pi skill link to .agents, when possible, or a verified copy |
.opencode/skills/<name> |
Optional | OpenCode skill link to .agents, when possible, or a verified copy |
.codex/config.toml |
Optional | Codex project MCP entries |
.mcp.json |
Optional | Claude Code project MCP entries |
.github/mcp.json |
Optional | GitHub Copilot CLI project MCP entries |
opencode.json |
Optional | OpenCode project config with managed MCP entries |
.aru/cache/ |
No | Immutable, content-addressed Git checkouts |
.aru/state.toml |
No | Local deployment mode and last-applied ownership digests |
.aru/transaction.toml |
No | Crash-recovery journal, present only during an interrupted operation |
aru init adds .aru/ to .gitignore. It does not ignore generated target paths, because each team can decide whether to commit them. During early development, aru.toml is intentionally unversioned and has no schema field.
For byte-level details about persisted data, see docs/formats.md.
🤖 Target capabilities
| Capability | Agents | Codex | Claude Code | Copilot CLI | pi | OpenCode |
|---|---|---|---|---|---|---|
Directory AGENTS.md |
Native | Native | Sibling import | Materialized root/path rule | Native | Native |
| Explicit instruction globs | Not supported | Not supported | .claude/rules/aru/** |
.github/instructions/aru/** |
Not supported | Not supported |
| Project skills | .agents/skills/ |
.agents/skills/ |
.claude/skills/ |
.github/skills/ |
.pi/skills/ |
.opencode/skills/ |
| stdio MCP | Not built in | command, args, env_vars |
type: stdio, command, args, ${ENV} |
type: stdio, mcpServers, ${ENV} |
Not built in | type: local, command array, {env:ENV} |
| Streamable HTTP MCP | Not built in | url |
type: http, url |
type: http, mcpServers |
Not built in | type: remote, url |
| Bearer environment reference | Not built in | bearer_token_env_var |
Authorization: Bearer ${ENV} |
Authorization: Bearer ${ENV} |
Not built in | Authorization: Bearer {env:ENV} |
| Environment-backed HTTP headers | Not built in | env_http_headers |
${ENV} header value |
${ENV} header value |
Not built in | {env:ENV} header value |
Aru rejects configurations that a selected target cannot represent rather than silently broadening or dropping behavior. Copilot MCP support is scoped to Copilot CLI's .github/mcp.json; VS Code's .vscode/mcp.json and GitHub.com MCP settings are separate contracts. See the original Codex/Claude MCP evidence and additional target capability evidence.
🛡️ Safety and recovery
Bounded, portable inputs
Aru treats instruction content, skill content, and Registry metadata as untrusted.
- Conventional discovery scans only the source root and
skills/**/SKILL.md, up to depth 6, 2,000 directories, and 20,000 entries. SKILL.mdis limited to 1 MiB, each selected regular file to 10 MiB, and each skill tree to 100 MiB.- Symlinks, devices, sockets, FIFOs, non-UTF-8 paths, case-folding collisions, Windows reserved names, and escaping selectors are rejected.
- Digests include a format version, portable path, executable marker, byte length, and raw bytes for every sorted regular file.
- Registry requests require HTTPS without URL userinfo. They use 10-second connect and 30-second total timeouts, at most three redirects, 10 MiB bodies, 100 pages, and 10,000 records.
- Malformed, oversized, truncated, cyclic, ambiguous, inactive, or unsupported metadata fails before writes.
Ownership protection
- MCP commands and arguments remain argv arrays. Aru never shell-expands or executes direct stdio commands.
- Aru stores only secret environment variable names or placeholders. It never reads secret values.
- Unmanaged instruction destinations and skill or MCP entries collide by default.
--mergepreserves unmanaged Markdown only around aru-owned instruction blocks.- Drifted owned entries are preserved and reported instead of overwritten.
- Only aru-owned server keys are merged or removed. Unrelated TOML comments, TOML keys, JSON entries, and OpenCode JSONC comments survive.
- Invalid existing configuration fails closed.
Atomic transactions
Every mutating command:
- takes
.aru/operation.lock; - rereads project inputs and validates the complete operation;
- stages each destination beside its final path;
- writes a durable journal;
- performs fixed-order atomic replacements with sibling backups.
A normal apply error immediately rolls back.
After a process kill or power loss, run any mutating command again:
aru sync
Before doing new work, aru reads .aru/transaction.toml and digest-gates a deterministic rollback to the complete old state. A dry run refuses to proceed while recovery is pending.
If a destination or backup contains unknown manual changes, recovery stops and preserves both the content and journal. Copy the affected project file and .aru/transaction.toml before manual repair. Do not delete backups until you understand whether each digest represents the old or new state.
If .aru/state.toml is lost, aru sync --locked adopts only entries whose semantic digests exactly match the committed projection-baseline. A different same-name entry remains an unmanaged collision. Baselines never authorize deletion of unknown historical orphans.
🧪 Offline demo
This example exercises initialization, add, locked replay, update, and remove without network access:
mkdir -p /tmp/aru-demo-source/skills/demo /tmp/aru-demo-project
printf '%s\n' '---' 'name: demo' 'description: Demo skill' '---' '# Demo' \
> /tmp/aru-demo-source/skills/demo/SKILL.md
git -C /tmp/aru-demo-source init -q
git -C /tmp/aru-demo-source config user.email demo@example.com
git -C /tmp/aru-demo-source config user.name Demo
git -C /tmp/aru-demo-source add skills/demo/SKILL.md
git -C /tmp/aru-demo-source commit -qm initial
git -C /tmp/aru-demo-source tag 1.0.0
cd /tmp/aru-demo-project
aru init --target codex --target claude
aru skill add /tmp/aru-demo-source --skill demo
aru --offline sync --locked
aru skill update /tmp/aru-demo-source
aru skill remove /tmp/aru-demo-source
Representative output is deterministic:
Created skill demo (.agents/skills/demo)
Created skill demo (.claude/skills/demo)
Locked skill demo 1.0.0
Updated aru.lock
Finished Project synchronized.
🛠️ Development
Serve or build the documentation with its locked toolchain:
just docs-serve
just docs-build
Run the CI-equivalent Rust checks:
cargo fmt --all -- --check
cargo clippy --locked --all-targets --all-features -- -D warnings
cargo test --locked --all-targets --all-features
Tests use temporary Git repositories, local Registry fixtures, and Unix PTYs (expectrl) for the real inquire keyboard flow. Live network access is reserved for an explicit, ignored public Git smoke test.
Release maintainers should follow docs/releasing.md. Aru is available under the MIT License.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file arust-0.0.7-py3-none-win_amd64.whl.
File metadata
- Download URL: arust-0.0.7-py3-none-win_amd64.whl
- Upload date:
- Size: 4.5 MB
- Tags: Python 3, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
95bd18b5d5dd72b385b906b5e2440d67ab49a5e001dfe226af01581068690f17
|
|
| MD5 |
b08e53af7960aaff37eaac5589ee35a7
|
|
| BLAKE2b-256 |
dddc446b3cef59d7f0bd075ce10c08fa96a61d5635df276eb0b7eb0787e35d04
|
Provenance
The following attestation bundles were made for arust-0.0.7-py3-none-win_amd64.whl:
Publisher:
pypi.yml on narumiruna/aru
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
arust-0.0.7-py3-none-win_amd64.whl -
Subject digest:
95bd18b5d5dd72b385b906b5e2440d67ab49a5e001dfe226af01581068690f17 - Sigstore transparency entry: 2535710746
- Sigstore integration time:
-
Permalink:
narumiruna/aru@996e6792364fb0f48a9f1998e6db509dc14eb74e -
Branch / Tag:
refs/tags/v0.0.7 - Owner: https://github.com/narumiruna
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yml@996e6792364fb0f48a9f1998e6db509dc14eb74e -
Trigger Event:
push
-
Statement type:
File details
Details for the file arust-0.0.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: arust-0.0.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 4.8 MB
- Tags: Python 3, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f99cf4c99b0f9b5722b7263f034da22042054f813063e51a74701ba6309119d1
|
|
| MD5 |
1fbd0b97970915b41863298f0959ca6e
|
|
| BLAKE2b-256 |
5d2ab3f9b4f2494ec95c48885a403626f63361551da42e1072eb8484bf3225ec
|
Provenance
The following attestation bundles were made for arust-0.0.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
pypi.yml on narumiruna/aru
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
arust-0.0.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
f99cf4c99b0f9b5722b7263f034da22042054f813063e51a74701ba6309119d1 - Sigstore transparency entry: 2535709868
- Sigstore integration time:
-
Permalink:
narumiruna/aru@996e6792364fb0f48a9f1998e6db509dc14eb74e -
Branch / Tag:
refs/tags/v0.0.7 - Owner: https://github.com/narumiruna
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yml@996e6792364fb0f48a9f1998e6db509dc14eb74e -
Trigger Event:
push
-
Statement type:
File details
Details for the file arust-0.0.7-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: arust-0.0.7-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 4.4 MB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cdc94848cc9bca4890e0b3290e0720df5c56b3ae0354c7c13162574072a38f10
|
|
| MD5 |
c31ab4e5ae9e5e915a1fbbfcebbbc4e9
|
|
| BLAKE2b-256 |
c46e9d09776cf341871d53ee4a3b2bf4496a37ff0d35194359f82d0638fc6baf
|
Provenance
The following attestation bundles were made for arust-0.0.7-py3-none-macosx_11_0_arm64.whl:
Publisher:
pypi.yml on narumiruna/aru
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
arust-0.0.7-py3-none-macosx_11_0_arm64.whl -
Subject digest:
cdc94848cc9bca4890e0b3290e0720df5c56b3ae0354c7c13162574072a38f10 - Sigstore transparency entry: 2535711871
- Sigstore integration time:
-
Permalink:
narumiruna/aru@996e6792364fb0f48a9f1998e6db509dc14eb74e -
Branch / Tag:
refs/tags/v0.0.7 - Owner: https://github.com/narumiruna
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yml@996e6792364fb0f48a9f1998e6db509dc14eb74e -
Trigger Event:
push
-
Statement type:
File details
Details for the file arust-0.0.7-py3-none-macosx_10_12_x86_64.whl.
File metadata
- Download URL: arust-0.0.7-py3-none-macosx_10_12_x86_64.whl
- Upload date:
- Size: 4.7 MB
- Tags: Python 3, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
23cc89f5b403f277c467e425afa10eb1a14c8a6f5d3a20e2bf33e8efa5f75b1f
|
|
| MD5 |
de143a484a836c55577f3d159195f403
|
|
| BLAKE2b-256 |
19703a64235483520a159c4dc2d0b27f66a1cb593ffb123e378a1681b7337967
|
Provenance
The following attestation bundles were made for arust-0.0.7-py3-none-macosx_10_12_x86_64.whl:
Publisher:
pypi.yml on narumiruna/aru
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
arust-0.0.7-py3-none-macosx_10_12_x86_64.whl -
Subject digest:
23cc89f5b403f277c467e425afa10eb1a14c8a6f5d3a20e2bf33e8efa5f75b1f - Sigstore transparency entry: 2535711310
- Sigstore integration time:
-
Permalink:
narumiruna/aru@996e6792364fb0f48a9f1998e6db509dc14eb74e -
Branch / Tag:
refs/tags/v0.0.7 - Owner: https://github.com/narumiruna
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yml@996e6792364fb0f48a9f1998e6db509dc14eb74e -
Trigger Event:
push
-
Statement type: