Dalo User Reference
This is the user-facing reference for scripting Dalo and for understanding the files Dalo writes. It documents the current CLI and persisted schemas.
Store Resolution
Dalo chooses the store path in this order:
--store <PATH>DALO_STORE~/.dalo
Relative store paths are resolved against the current working directory. ~ is expanded when used at the start of a path.
Environment Variables
| Variable | Purpose |
|---|---|
DALO_STORE |
Override the default store path; --store takes precedence. |
DALO_GIT_TIMEOUT_SECS |
Positive timeout in seconds for every Git subprocess. Invalid or zero values use the built-in defaults. |
DALO_OFFLINE |
Disable passive update checks when set to a truthy value. |
DALO_UPDATE_CHECK |
Set to never to disable passive update checks. |
NO_COLOR |
Disable ANSI color output when set. |
DALO_TARGET |
Installer-only release target override. A non-empty value takes precedence over platform detection; see installer target variables. |
For installation variables, see the README installation section
and the npm launcher README: DALO_VERIFY,
DALO_LINUX_LIBC, DALO_INSTALL_DIR, DALO_VERSION, and DALO_CACHE_DIR.
DALO_TARGET
DALO_TARGET is read only by https://dalo.sh/install.sh; it is not a Dalo
CLI option and does not affect an installed binary. An unset or empty value
uses automatic detection: macOS chooses its x86_64 or aarch64 target, and
Linux chooses x86_64 or aarch64 plus the detected (or
DALO_LINUX_LIBC-overridden) libc. A non-empty value takes precedence and is
used verbatim to form the release archive name. Set it only to a published target:
x86_64-unknown-linux-gnu, aarch64-unknown-linux-gnu,
x86_64-unknown-linux-musl, aarch64-unknown-linux-musl,
x86_64-apple-darwin, or aarch64-apple-darwin. The installer does not
pre-validate the override; another value fails when its release archive cannot
be fetched.
Global Flags
Global flags can be placed before or after the command.
| Flag | Meaning |
|---|---|
--store <PATH> |
Use a store other than the resolved default. |
--json |
Emit machine-readable JSON for commands that support structured output. |
--yes |
Compatibility flag accepted for existing scripts but hidden from command help. It is currently a no-op and never implies --replace, creates commits, or grants new approvals. |
--dry-run |
Plan supported mutating operations without writing files, cloning, linking, or changing locks. Read-only commands ignore it. |
-h, --help |
Print command help. |
-V, --version |
Print the installed version. |
Update Notices
After a successful interactive command, Dalo checks for a newer GitHub release
at most once per 24 hours. The cached check uses a one-second network timeout and
never changes the command's exit status. Checks are skipped for --json, CI,
DALO_OFFLINE=1, and DALO_UPDATE_CHECK=never.
Dalo never modifies its own executable. If the installed version is outdated,
the notice recommends an upgrade command for Homebrew, npm/npx, mise, Cargo, or
the hosted installer. Launchers may set DALO_INSTALL_CHANNEL so the Rust binary
can preserve their installation context. Unknown installation methods receive a
link to the installation guide instead of a guessed command. Each newer version
is announced only once per user cache.
Command Reference
dalo init
Initialize the store layout, default config, local Git source, lock/state files, and approvals file.
Examples:
dalo init
dalo --store /tmp/dalo-demo init
dalo --json --dry-run init
JSON output shape: InitReport.
dalo next
Show a compact summary of the selected store and one copyable next action. It
chooses initialization, target discovery, source addition, an exact pending
approval, synchronization, or detailed status when the already-computed store
facts contain errors or inventory warnings. Health problems take precedence
over onboarding guidance. Only when no action is needed does it report
All synced.
Running bare dalo shows this same summary only when stdout is a terminal;
when output is piped it keeps printing the normal static help. Use dalo next
in scripts or whenever you want the state-aware result explicitly.
dalo next
dalo --store /tmp/dalo-demo next
dalo --json next
JSON output shape: NextActionReport with store counts, state, message,
and an optional copyable command.
dalo team init <source-id>
Create dalo.toml in the current team repository. Use --repo <path> on the
team command to target another checkout. Team-management commands do not read
or initialize the personal Dalo store, and they do not commit or push changes.
The global --store flag is accepted for uniformity but has no effect on team
commands; select the target repository with --repo instead. They write the
manifest in canonical TOML form; catalog mutations may normalize formatting and
do not preserve comments.
Examples:
dalo team init company --name "Company Skills"
dalo team --repo ../company-skills init company
dalo --dry-run team init company
An existing manifest with the same source ID is left unchanged. A different ID
is never overwritten. JSON output shape: TeamManifestMutationReport.
dalo team catalog add <id> <git-url-or-path> --version <revision>
Add a pinned external skill set to the team manifest. Repeat --skill for
include/exclude filters; omitting it means all skills.
dalo team catalog add marketing https://github.com/coreyhaines31/marketingskills.git \
--version 0123456789abcdef0123456789abcdef01234567 \
--skill +copywriting \
--skill +launch \
--skill -seo-audit
Use --priority <number> to override the derived default. JSON output shape:
TeamManifestMutationReport.
dalo team catalog skills <id> [filter]...
Replace the complete filter list. Calling the command without filters sets
skills = [], which means all skills.
dalo team catalog skills marketing +copywriting +launch -seo-audit
dalo team catalog skills marketing
JSON output shape: TeamManifestMutationReport.
dalo team catalog version <id> <revision>
Change the requested commit, tag, or ref. The next dalo sync on each team
member's machine stages, audits, and pins the resolved commit before publishing
it.
dalo team catalog version marketing v2.0.0
JSON output shape: TeamManifestMutationReport.
dalo team catalog update <id> --from <ref>
Resolve an upstream branch, tag, or ref in a temporary clone, compare the
currently declared version with the candidate inventory, and run deterministic
audits for the selected candidate skills. A successful real update writes the
exact candidate commit to dalo.toml; it never leaves the shared version as a
floating ref and never commits or pushes the repository.
dalo --dry-run team catalog update marketing --from main
dalo --json --dry-run team catalog update marketing --from v2
dalo team catalog update marketing --from main
dalo team catalog update marketing --from main \
--accept-risk "reviewed pinned automation"
Dry-run performs network reads and temporary filesystem work but does not edit
the repository or personal Dalo store. A non-fast-forward candidate, a removed
selected skill, an invalid candidate selection, or a blocking audit finding
prevents the write. --accept-risk <reason> is required to be non-empty and
accepts only blocking security-audit findings from this exact candidate. It
does not bypass non-fast-forward updates, removed skills, invalid selections,
or other structural blockers. Each accepted audit report retains its
content-bound risk_acceptance scope hash; no personal store state is written.
JSON output shape: TeamCatalogUpdateReport, including
old_version, exact old_commit and candidate_commit, outcomes[],
audits[], accepted_risk_reason, blocking_reasons[], dry_run, and
updated.
dalo team catalog remove <id>
Remove the declaration. The next team-member sync removes generated source state, approvals, owned links, and checkout state for that catalog.
JSON output shape: TeamManifestMutationReport.
dalo team show
Print the source identity and catalog declarations from dalo.toml. Use
--json for TeamManifestView.
dalo target detect
List known agent targets, their linked paths when configured (otherwise their
default paths where known), whether those paths exist, and whether they are
linked in Dalo state. The text output finishes with the next link command when
it finds an installed-but-unlinked agent, a repair command when a recorded
target path is missing, or a generic-folder command when no agent folder is
present. dalo target list is an alias for this command.
Examples:
dalo target detect
dalo --json target detect
Built-in target IDs:
| ID | Default path | Support |
|---|---|---|
codex |
~/.agents/skills |
supported |
claude |
~/.claude/skills |
supported |
openclaw |
~/.agents/skills |
supported |
hermes |
~/.hermes/skills |
supported |
generic |
none, path required | supported |
cursor |
none | experimental |
opencode |
none | experimental |
JSON output shape: TargetDetectReport.
dalo target link <target> [path]
Record a target materialization directory. The generic target requires an explicit path. Known targets can use their default path or an explicit override.
Examples:
dalo target link codex
dalo target link generic ./tmp/agent-skills
dalo --dry-run target link claude ~/.claude/skills
When a target path does not exist yet, Dalo creates its missing directory
ancestors only after validating the state update. If persisting state.toml
fails, newly created empty ancestors are removed again; pre-existing directories
and any concurrent content are preserved.
JSON output shape: TargetLinkReport.
dalo target unlink <target>
Disable a target in state. unlink itself removes nothing from the target
directory. The next dalo sync then reconciles the target and removes the
Dalo-owned links it had materialized there; unmanaged files and real
directories are never touched.
Examples:
dalo target unlink codex
dalo --json target unlink generic
JSON output shape: TargetUnlinkReport.
dalo source add <id> <git-url-or-path> [--namespace <prefix>]
Add a trusted team source, clone it into sources/<id>/checkout, configure it
with update_policy = "track", and run a deterministic security preflight for
every discovered skill. Source IDs must be a single path component using only
letters, digits, ., _, and -; . and .. are rejected.
Local paths are supported; relative paths resolve against the current working
directory.
Examples:
dalo source add platform git@github.com:example/platform-skills.git
dalo source add company git@github.com:example/company-skills.git --namespace company
dalo --dry-run source add team https://github.com/example/team-skills.git
JSON output shape: SourceAddReport.
When discovery skips or degrades a skill, source add prints each inventory
warning with its path and actionable reason before continuing to audit the
valid skills. Skipped skills are not audited or materialized. JSON consumers
receive the same typed entries in SourceAddReport.inventory_warnings[].
dalo source add-catalog <id> <git-url-or-path> [--namespace <prefix>]
Add an untrusted catalog source, clone it into sources/<id>/checkout, and
configure it with update_policy = "pin". Catalog skills are offers; nothing
from a catalog becomes active until selected and approved.
After adding a catalog, the CLI reports how many skills are available and prints
the exact source inspect and source select commands for the next step.
Local paths are supported; relative paths resolve against the current working
directory.
Examples:
dalo source add-catalog public https://github.com/example/skill-catalog.git
dalo source add-catalog editorial https://github.com/example/editorial-skills.git --namespace editorial
dalo source inspect public
dalo source select public review-helper
JSON output shape: SourceConfig.
dalo source list
List configured sources in priority order. Git-backed entries include a
read-only provenance object assembled from config, source-lock.toml, and the
checkout without fetching: management authority, credential-redacted origin,
requested ref, resolved pin, and checkout commit.
Examples:
dalo source list
dalo --json source list
JSON output shape: SourceListReport.
dalo source priority <id> <priority>
Change a source priority. Lower numbers win during resolution. The local source priority is fixed and cannot be changed.
Examples:
dalo source priority platform 10
dalo --dry-run source priority platform 20
JSON output shape: SourcePriorityReport.
dalo source namespace <id> [<prefix>] [--clear]
Set an optional namespace for every skill from a configured source.
Dalo installs namespaced skills as <prefix>__<skill> and resolves them under
that name, so same-named skills from distinct namespaced sources can coexist.
The source SKILL.md files and source-qualified approval identities remain
unchanged. Prefixes use the same portable lowercase token rules as skill names.
Use --clear to restore the source's original install names. The built-in
local source cannot be assigned a namespace, but --clear can restore its
original slot names if a legacy configuration contains one, so local adaptations
continue to override matching managed skills.
Examples:
dalo source namespace company company
dalo source namespace company --clear
JSON output shape: SourceNamespaceReport.
dalo source inspect <id>
Inspect a catalog source and list available candidate skills, including ID, slot name, path, description, dependencies, and selection status.
Examples:
dalo source inspect public
dalo --json source inspect public
JSON output shape: CatalogInspectReport.
dalo source select <id> <skill>...
Select catalog skills by stable frontmatter ID, <source-id>:<slot> reference,
or slot name. Selection runs the deterministic security preflight, writes
config.toml, and updates source-lock.toml with the pinned commit and
inventory snapshot. Human-readable output names the skills added or removed,
reports no-op requests explicitly, and shows the complete resulting selection
as secondary detail.
Examples:
dalo source select public review-helper
dalo source select public review-helper formatter
dalo source select public --unselect formatter
dalo --dry-run source select public review-helper
JSON output shape: CatalogSelectReport.
dalo source refresh <id>
Fetch a catalog source and compare the upstream inventory with the pinned
inventory snapshot. This is read-only for pins and selections. --check exits
non-zero when selected skills drifted upstream. --advance explicitly updates
only this catalog after candidate approval, dependency, audit, and
materialization preflight. Selected removal, dirty or divergent checkouts,
security-audit blocks, and unsafe target state stop the transaction.
Examples:
dalo source refresh public
dalo source refresh public --check
dalo --json source refresh public
dalo --dry-run --json source refresh public --advance
dalo source refresh public --advance
JSON output shape: CatalogDrift.
With --check, the command exits with code 1 when a selected skill changed,
moved, or was removed upstream. New unselected offerings remain informational.
--advance and --check are mutually exclusive. Global --dry-run with
--advance returns CatalogAdvanceReport, including the complete old and new
catalog lock entries, stable drift codes, reconciled selection, security audit
results, materialization plan, and blocking reasons. It performs no config,
lock, checkout, audit-cache, state, or target writes. A real advance updates the
checkout, source-lock.toml, any stable-ID move in config.toml, lock.toml,
and affected owned target links as one rollback-safe transaction. Newly
required unapproved skills remain unlinked and can be approved after the new
pin is installed; their dependents remain blocked until then. A candidate with
blocking audit findings stays in sources/.audit-staging/; the report prints
the exact staged path to review and, when justified, accept for that content
hash before retrying the advance.
dalo source remove <id>
Remove a team or catalog source as one coordinated change. Dalo first reconciles
only links it owns, then removes the source from config.toml, its catalog lock
entry (when present), and approvals qualified with that source ID. The source
checkout is removed after the durable store state is committed. Use
--keep-checkout to retain it for manual inspection. The built-in local
source cannot be removed. A retained checkout must be moved or removed before
the same source ID can be added again.
Examples:
dalo --dry-run --json source remove platform
dalo source remove public
dalo source remove public --keep-checkout
Both dry-run and real --json output use SourceRemoveReport. It lists
deactivated skills, the operation kind for every reconciled owned link, and any
non-fatal checkout cleanup warnings. Dry-run does not modify config, locks,
approvals, checkouts, or targets.
dalo status
Show source scans, linked targets, active skills, pending approvals, unlinked skills, user-lock drift, unmanaged target skills, instruction packs, topic overlaps, and instruction block drift.
Examples:
dalo status
dalo status --check
dalo --json status
JSON output shape: StatusReport.
--check exits with code 1 for unresolved source scans, skill or agent inventory warnings,
pending approvals, blocked required closure, blocking or failed security audits,
blocked materialization operations, missing targets for active skills, actionable
resolution diagnostics, lock drift, unmanaged blockers, instruction-block drift,
or unhealthy autosync state. It keeps the full report on stdout for JSON
consumers.
dalo plan
Show the effective plugin setup for every linked target without changing source,
approval, or target files. Use it before sync to review selected plugins,
target compatibility, approval state, and provider package paths. Planning never
runs tools or hooks. Pass --target to limit the report to one linked target.
dalo plan
dalo plan --target codex
dalo --json plan
JSON output shape: InstallationPlan.
dalo agent list|show <source>:<name>
Canonical agent packages live in agents/<name>/AGENT.md inside a source.
agent list shows active, pending, and shadowed packages; agent show previews
the package for Claude and Codex without writing provider files.
dalo agent list
dalo agent show local:reviewer --provider codex
dalo approve agent team:reviewer
Non-local agents need explicit approve agent <source>:<name> records; skill,
source, author, and org approvals do not activate them. Invalid packages also
make status --check fail. JSON shapes: AgentListReport (resolution,
inventory_warnings[], source_errors[]) and AgentShowReport (agent,
compilations[]).
dalo sync
Refresh clean tracking team sources, resolve the desired skill set, materialize owned symlinks into linked targets, and write lock.toml. Dirty tracking sources block refresh. Dalo does not overwrite unmanaged real directories or foreign symlinks.
Before materialization, Dalo audits the exact content hash of every active
skill. Unaccepted high or critical findings stop the command before any
links are changed. A previously recorded risk acceptance is reused only while
the complete directory hash, audit-engine versions, coverage, and finding set
remain unchanged.
Tracking team updates are fetched and audited in a detached worktree below
sources/.audit-staging/ before the live checkout fast-forwards. Existing
target links therefore continue to expose the last accepted commit. When an
update is blocked, the error prints a command for auditing and accepting the
exact staged skill; the next sync reuses that staged hash.
Examples:
dalo sync
dalo sync --check
dalo --dry-run sync
dalo --json sync
JSON output shape: SyncReport. deliveries[] records each logical skill and
physical target slot with target_ids, mode, optional provider, selected
artifact_path, content fingerprint, and any fail-closed reason.
dalo --dry-run sync does not fetch tracking team sources, so it prints a
note when upstream changes are not reflected in its plan. Run a real
dalo sync to fetch those sources first; JSON consumers can inspect
SyncReport.unrefreshed_tracking_sources[].
sync --check still renders the report, then exits with code 1 when materialization
is blocked or incomplete, including pending approvals, resolution diagnostics,
degraded sources, blocked operations, or active skills without linked targets.
An enabled source is degraded when Dalo cannot safely scan it, for example
because its checkout is missing or unreadable, a tracking refresh failed, or
inventory warnings make removals ambiguous. Dalo preserves recorded owned links
from that source instead of treating the incomplete scan as a deletion. A normal
sync can still apply unrelated safe work and exits successfully; sync --check
exits with code 1 until the source is healthy. Restore or re-clone the checkout,
or remove the source with dalo source remove <id>. Do not adopt or delete the
preserved target link as if it were an unmanaged conflict. Machine-readable
consumers can inspect each affected source in SyncReport.degraded_sources[].
sync also prints the individual inventory warnings that caused a degraded
scan, including the affected path and reason, so the removal-safety message is
not the only diagnosis. JSON consumers can inspect the same typed entries in
SyncReport.inventory_warnings[].
Lock drift for local and team sources is commit-based. Uncommitted working-tree edits do not change the recorded commit, and materialized symlinks expose those live edits directly. Catalog selections are the source kind with content and metadata fingerprints for upstream drift checks.
dalo autosync install|status|uninstall
Install recurring dalo sync --check behavior through the current user's
native scheduler. macOS uses launchd. Linux prefers a systemd user timer and
falls back to cron only when the user manager is unavailable. Supported
schedules are hourly, daily (default for a first install), and weekly.
Omitting --schedule on a reinstall preserves the installed schedule.
Daily and weekly schedules run at a fixed per-store time in the local
early-morning window (00:00–05:59, derived from the store path so different
stores stagger rather than all firing at once). launchd coalesces missed jobs
on wake and the systemd timer uses Persistent=true, but the cron fallback has
no catch-up: a machine powered off throughout its scheduled window simply waits
for the next slot, so prefer hourly on machines that are usually asleep at
night. The window also overlaps the daylight-saving transition, so a skipped or
repeated local hour can shift a single run.
dalo autosync install
dalo autosync install --schedule hourly
dalo --json autosync status
dalo autosync uninstall
Installation records the stable absolute executable or launcher path that was
invoked, preserving Homebrew symlinks and the global npm launcher instead of
pinning their version-specific targets. Temporary npx executions cannot
install autosync; install getdalo globally or use another persistent Dalo
installation first. Generated artifacts never depend on shell startup files.
Reinstalling or removing the job is idempotent. Global --dry-run previews
install and uninstall without writing config, metadata, native artifacts, or
scheduler state. Re-run autosync install after moving the Dalo executable;
status treats a missing recorded executable as disabled instead of guessing a
replacement, and doctor reports the exact missing path.
If autosync.toml is malformed or uses a newer unsupported schema,
autosync uninstall quarantines it as autosync.toml.corrupt-*, reconstructs
the native scheduler identifiers from the store path for best-effort cleanup,
and leaves autosync ready for a clean reinstall.
The internal scheduled runner acquires the store lock once without waiting. If
an interactive Dalo process owns it, the run exits successfully as skipped
and retries on the next schedule. Dirty sources, malformed locks, pending
approvals, security findings, target conflicts, or managed instruction drift
remain fail-closed. autosync-run.toml records the last attempted and last
successful timestamps plus running, succeeded, skipped, or blocked and
an actionable reason. A run left running well past its schedule interval —
for example after a crash or power loss mid-sync — is surfaced by status and
doctor as an interrupted run.
autosync status, normal status, and doctor all surface this durable
state; non-JSON output renders timestamps as UTC calendar times and, when an
installed job is disabled, names the specific cause (missing artifacts, a moved
store, or a scheduler-reported disable). Logs are written to autosync.log and
autosync-error.log in the store. Before each scheduled run, Dalo trims each
file to roughly its most recent 1 MiB, marking discarded older output with a
truncation line. Both files are removed on autosync uninstall.
dalo adopt <skill> [--replace]
Copy an unmanaged target skill into local/skills/<slot>. With --replace, Dalo replaces the original unmanaged directory with an owned symlink after copying. Without --replace, the original directory remains untouched.
Adoption runs the same deterministic security preflight before copying or
replacing anything. --reviewer (with deprecated --agent alias), --refresh-audit, and --accept-risk <reason>
have the same meaning as on dalo approve skill.
The <skill> argument can be a slot name, a disambiguating path, or an ID reported by status or resolve list. If the slot name exists in more than one target, Dalo refuses the ambiguous selector and lists the paths to choose from.
Before it audits or copies anything, adoption rejects a folder name or
SKILL.md frontmatter name that is not a portable lowercase slot name.
Rename the folder or correct the frontmatter first, then run dalo adopt
again.
Examples:
dalo adopt review-helper
dalo adopt review-helper --replace
dalo --dry-run adopt /path/to/target/review-helper
When --replace reuses an existing local copy, Dalo compares the complete
directory shape before removing the unmanaged original: file bytes and
executable bits, empty directories, and symlink targets must all match.
Successful JSON output combines the preflight and mutation as
{ "audit": AuditReport, "adoption": AdoptReport }. If the audit blocks the
operation, Dalo prints only the blocking AuditReport and exits non-zero.
dalo resolve list
List repairable unmanaged skills, target scan warnings, and recorded owned symlinks.
Examples:
dalo resolve list
dalo --json resolve list
JSON output shape: ResolveListReport.
dalo resolve adopt <id> [--replace]
Adopt an unmanaged skill by an ID returned from resolve list. Behavior matches dalo adopt.
Examples:
dalo resolve adopt review-helper
dalo resolve adopt review-helper --replace
JSON output matches dalo adopt: successful output is
{ "audit": AuditReport, "adoption": AdoptReport }; a blocking audit prints
only AuditReport and exits non-zero.
dalo resolve keep <id>
Protect an unmanaged target skill so Dalo reports it as intentionally unmanaged. Protection is stored by logical target and slot, follows later target-path updates, and turns the sync conflict into a non-failing keep operation. An explicit resolve adopt --replace remains an override.
Examples:
dalo resolve keep review-helper
dalo --dry-run resolve keep review-helper
JSON output shape: KeepReport.
dalo resolve unkeep <target>:<slot>
Remove protection from one target slot. A bare slot name removes matching protection across targets.
Examples:
dalo resolve unkeep claude:review-helper
dalo --dry-run resolve unkeep review-helper
JSON output shape: UnkeepReport.
dalo resolve remove-owned <id>
Remove a recorded owned symlink by ID. If the recorded path is already missing, Dalo drops the stale state record. If a different, foreign symlink occupies the path, Dalo leaves that symlink untouched and drops only the stale ownership record. If a real entry exists at that path, Dalo blocks removal.
Examples:
dalo resolve remove-owned claude:review-helper
dalo --json resolve remove-owned claude:review-helper
JSON output shape: RemoveOwnedReport.
dalo doctor
Run read-only diagnostics for store layout, config, state, lock, approvals, Git, GitHub CLI, targets, owned symlinks, dirty sources, pending approvals, required closures, instruction packs, and cloud-synced target paths.
Examples:
dalo doctor
dalo doctor --check
dalo --json doctor
JSON output shape: DoctorReport.
--check exits with code 1 when the report contains an error finding. Warnings
remain report-only so CI can choose its own warning policy.
Doctor emits source_lock_ok only when source-lock.toml exists and parses. If
the file is malformed, it reports source_lock_invalid and suppresses dependent
catalog provenance comparisons so recovery guidance cannot contradict itself.
dalo audit <skill-or-path>
Inspect a skill before it is exposed to an agent. The target can be an existing directory or a source-qualified reference. Deterministic checks are local and never execute skill code.
dalo audit public:review-helper
dalo audit ./my-skill --check
dalo audit public:review-helper --reviewer auto
dalo --json audit public:review-helper --reviewer codex
dalo audit public:review-helper --reviewer claude --refresh-audit
Use --refresh-audit to ignore a compatible cached semantic review and run the
selected provider again. The older --refresh spelling remains a hidden alias
for script compatibility.
--reviewer auto|codex|claude|opencode adds a semantic review through an installed
agent CLI. Dalo starts a fresh non-persistent reviewer and treats a bounded
snapshot as untrusted data. Claude and OpenCode run with tools denied. Codex
currently retains its network-disabled, read-only sandbox shell, so Dalo never
selects it through auto; choosing --reviewer codex is an explicit acceptance of
that weaker isolation boundary. User configuration, project rules, skills,
plugins, and MCPs are disabled where the provider supports it. The structured
result contains evidence-backed findings, expected capabilities, and behavior
not disclosed by the skill. Depending on the installed agent configuration,
this can send skill contents to an external model provider and consume that
provider's quota. Dalo never includes .git metadata in that snapshot; a skill
containing a .git entry receives a blocking, partial-coverage finding instead.
Provider processes receive only an explicit runtime and provider-authentication
environment allowlist rather than inheriting Dalo's full environment. Omitting
--reviewer is fully local. --agent remains a deprecated compatibility alias.
Agent review is optional and additive, not an approval mechanism. It can add
evidence-backed findings to the deterministic audit, but it never clears a
deterministic finding or certifies a skill as safe. A review with no additional
findings means only that this constrained assessment found no additional issue;
it is not an endorsement or safety guarantee. sync does not invoke a provider
on its own. Its human-readable result repeats that boundary after every sync.
--check exits non-zero for unaccepted high or critical findings. Record a
reviewed exception with a non-empty reason:
dalo audit public:review-helper \
--accept-risk "reviewed pinned upstream installer"
Persistence changes (such as shell startup files, scheduled tasks, or agent
configuration) and privileged command execution are high findings and block
by default. General dynamic execution remains a medium review finding: it is
reported, but does not block materialization on its own. This policy keeps
high-confidence persistence and privilege-escalation primitives behind an
explicit, content-bound risk acceptance without treating every technical skill
as unsafe by default.
Reports live below audits/ and are keyed by both the source-qualified skill
reference and the complete skill directory hash. After re-hashing the current
directory, a report with the matching source, static-engine version, and scan
mode reuses its deterministic findings and coverage instead of reading and
scanning every file again. Missing, malformed, old-version, changed-content,
unreadable, or incompatible-mode reports are rebuilt before they can affect the
result.
When a non-dry-run audit produces the same durable report content, Dalo retains
the existing report (including its scanned_at_unix value) without rewriting
it.
Cached agent results additionally require the same content, scan mode,
provider, and Dalo review-prompt version. Risk acceptance is bound to source
provenance, engine versions, coverage, and exact deterministic and semantic
findings, so a different source or newly discovered risk requires a new
decision even when the skill bytes did not change.
The audit directory and report files are restricted to the current user when Dalo writes them. Audit state is still a local trust boundary rather than a cryptographically authenticated log: a process running as the same user can replace it. Protect the store like other security-sensitive user state and do not place it in a shared or untrusted writable directory. No-finding results are best-effort observations, not a security certification.
JSON output shape: AuditReport.
dalo plugin list|show|select|unselect|decline
Inspect and manage direct local plugin selection. Plugin references use
<source-id>:<slot-or-stable-id>.
dalo plugin list
dalo plugin show company:review-workflow
dalo plugin select company:review-workflow
dalo plugin unselect company:review-workflow
dalo plugin decline company:review-workflow \
--rule-id no-shell-hooks \
--reason "shell hooks are outside local policy"
list returns every valid candidate plus the canonical selected graph; show
returns one candidate and its selected state, when reachable. Both commands are
read-only. select adds a direct user selection without replacing
source-authored selections, while unselect removes only that direct user
selection. decline retains selected intent but blocks the plugin with a local
policy record. It requires the plugin to be selected, a unique lower-kebab
--rule-id, and a non-empty --reason for audit context.
The three mutations support --dry-run and report whether configuration would
change. JSON shapes: PluginListReport (candidates[], resolution),
PluginShowReport (candidate, optional selected), and
PluginMutationReport (plugin, action, changed, dry_run).
dalo plugin review <source:plugin>
Review every component decision for one selected portable plugin and its selected dependency closure in deterministic plugin/component/target order:
dalo plugin review company:review-workflow
dalo --dry-run plugin review company:review-workflow
dalo --json plugin review company:review-workflow
The report embeds the same typed installation-plan facts as dalo plan, plus
package provenance, content/contract hashes, agent activation, inactive
instruction recommendations, tool capabilities, hook event/effect/matcher/
timeout/failure semantics, and provider mappings or fallbacks. Existing exact
approvals are marked reused; changed hash-bound contracts are invalidated;
blocked, unsupported, and inactive boundaries stay distinct.
Interactive mode collects y/n answers in memory and requires a final
confirmation before one atomic approval-ledger write. EOF, q, or declining
the final confirmation grants nothing. The displayed review token is rebuilt
under the store lock immediately before commit, so source, approval, audit, or
target drift requires a fresh review. Only the displayed exact skill,
agent, tool, and hook values can be committed—never a plugin/source/
author/org/wildcard approval. Tool bytes may be content-addressed and staged as
an inert prepare step; tools, hooks, generators, semantic reviewers, and target
mutations are never executed by review.
JSON and dry-run modes are read-only and do not prompt. Prefer the individual
commands below for a single known component, for revocation, or when a skill's
blocking findings require --accept-risk.
dalo tool list; dalo tool show|audit <source:plugin#tool:id>
Inspect plugin-local executable contracts without running them:
dalo tool list
dalo tool show company:review-workflow#tool:detector
dalo tool audit company:review-workflow#tool:detector
dalo --json tool show company:review-workflow#tool:detector
list joins validated tools with their approval, immutable staging, runtime,
platform, and audit state. show returns the full descriptor, contract hash,
source provenance, exact approval value, staged path when present, and an
actionable diagnostic. audit rechecks the tool's declared executable closure
and contract hash; it does not stage, approve, or execute the tool.
JSON shapes: ToolListReport (tools[], warnings[]), ToolStatusReport
(tool, plugin_package_hash, plugin_path, source_provenance,
approval_value, state, optional staged_path, diagnostic), and
ToolAuditReport (tool, contract_hash, plugin_package_hash, passed,
findings[]).
dalo hook list; dalo hook show <source:plugin#hook:id>
Inspect portable hook contracts without installing or executing them:
dalo hook list
dalo hook show company:review-workflow#hook:check-shell
dalo --json hook show company:review-workflow#hook:check-shell
list reports every validated hook with its independent trust state and the
referenced tool's state. show returns the exact hook and tool contracts,
source provenance, approval value, event/effect/matcher/binding semantics, and
an actionable diagnostic. A hook becomes ready only when both its own contract
and its referenced tool contract are ready. These public inspection commands
never project or execute a hook.
JSON shapes: HookListReport (hooks[], warnings[]) and HookStatusReport
(hook, plugin_package_hash, source_provenance, approval_value,
tool_state, tool, state, diagnostic).
dalo approve
Grant, list, and revoke approval records without editing approvals.toml.
Component and owner values are source-qualified, so an approval cannot
accidentally apply to a different source with the same name.
dalo approve list
dalo approve skill public:review-helper
dalo approve skill public:review-helper --reviewer codex
dalo approve skill public:review-helper --accept-risk "reviewed exception"
dalo approve agent team:reviewer
dalo approve tool team:quality#tool:detector
dalo approve delivery team:generated-review
dalo approve hook team:quality#hook:pre-commit
dalo approve source team
dalo approve author public:maintainers
dalo approve org public:example-org
dalo approve revoke skill public:review-helper
dalo approve revoke tool team:quality#tool:detector
dalo approve revoke delivery team:generated-review
dalo approve revoke hook team:quality#hook:pre-commit
Approval writes support --dry-run and --json. A pending skill shown by
status can be approved narrowly with dalo approve skill <source:skill>.
A pending canonical agent shown by agent list can be activated with
dalo approve agent <source:agent>. Tool approval validates and immutably
stages the exact executable closure without running it. Delivery approval is
inert and grants only the exact revision- and recipe-bound generated delivery.
Hook approval grants the exact hook contract after its referenced tool is
ready. The revoke scope is one of skill, agent, tool, delivery, hook,
source, author, or org; Clap validates this value and exposes the choices
to shell completion.
Skill approval always runs the deterministic preflight first and refuses a
blocking result unless a reason is supplied with --accept-risk. --reviewer
adds the same isolated semantic review as dalo audit.
JSON output shapes: ApprovalsFile for list; successful approve skill
output is { "audit": AuditReport, "approval": ApprovalReport }; agent,
source, author, and org mutations emit a bare ApprovalReport; tool,
delivery, and hook grants and revocations emit ToolApprovalReport,
DeliveryApprovalReport, and HookApprovalReport, respectively. Other
revocations emit ApprovalReport. If the skill audit blocks approval, Dalo
prints only the blocking AuditReport and exits non-zero.
dalo instructions enable <pack-ref> <file|--target agent...>
Render a local pack from local/instructions/<pack>.md, or a source-backed pack
selected as <source>:<pack>, into an instruction file as a managed block. The
target file is created if missing. Enabling the same pack again is idempotent
and refreshes the block. Source-backed packs must be tracked in a clean Git
checkout; Dalo records the exact source commit and declared pack version in the
user lock. Running instructions enable is the explicit activation boundary:
discovering or refreshing a source never activates a new pack automatically.
Repeat --target to resolve one pack to several verified native user files in
one operation. codex maps to $CODEX_HOME/AGENTS.md (default
~/.codex/AGENTS.md) and claude maps to
$CLAUDE_CONFIG_DIR/CLAUDE.md (default ~/.claude/CLAUDE.md). Existing
symlinks are resolved before planning, so aliases of the same physical file are
written once. Targets without a verified mapping fail closed and require an
explicit file.
Examples:
dalo instructions enable team-style ~/.codex/AGENTS.md
dalo instructions enable company:engineering-defaults ~/.claude/CLAUDE.md
dalo instructions enable company:engineering-defaults --target codex --target claude
dalo --dry-run instructions enable team-style ./AGENTS.md
Explicit-file JSON output uses InstructionPackReport. Target-aware output uses
InstructionPackBatchReport with source_id, pack_id, dry_run, and
de-duplicated operations[]; every operation includes logical_targets[], the
effective physical target, action, and an optional warning.
dalo instructions disable <pack-ref> <file|--target agent...>
Remove a pack's managed block from an instruction file and remove its active lock entry.
Examples:
dalo instructions disable team-style ~/.codex/AGENTS.md
dalo instructions disable company:engineering-defaults ~/.claude/CLAUDE.md
dalo instructions disable company:engineering-defaults --target codex --target claude
dalo --json instructions disable team-style ./AGENTS.md
JSON output shape: InstructionPackReport with source_id, pack_id, target,
action, dry_run, and an optional warning when recovery leaves a malformed
target block untouched. Disabling a pack removes its lock entry even when its managed
markers are malformed; the target file is left unchanged and the warning
explains the remaining drift. Mutations abort if the target changed on disk
after it was read. Target updates lock the opened inode and verify both its
content and identity before and after writing, so a file replaced by another
process is left untouched and the command fails safely.
dalo instructions list
List active instruction packs recorded in lock.toml.
Examples:
dalo instructions list
dalo --json instructions list
JSON output shape: InstructionPackListReport with
active_instruction_packs[] entries.
dalo completions <shell>
Generate shell completions to stdout. Supported shell names are provided by clap_complete, including bash, zsh, and fish.
Examples:
dalo completions zsh > _dalo
dalo completions bash > dalo.bash
dalo completions fish > dalo.fish
Release archives include generated completions. This command is also available for Cargo installs and local shell setup.
dalo manpage
Generate the dalo(1) man page to stdout from the same Clap command definition used for --help.
Example:
dalo manpage > dalo.1
Release archives include the generated man page. This command is also available for Cargo installs and local documentation setup.
Exit Codes
Dalo uses a small scripting contract:
| Code | Name | Meaning |
|---|---|---|
0 |
success | Command completed. |
1 |
expected failure | User-actionable input/state problem, such as semantic value validation, unknown source, unknown target, unsupported schema, parse error, a failed explicit check, a security-audit block during sync or approve, or adoption destination already existing. |
2 |
usage error | Invalid arguments or flags from Clap. This output is plain text even with --json. |
3 |
unsafe state | Dalo refused to mutate because the state needs human attention, such as a dirty source, active store lock, or malformed instruction block. |
4 |
environment problem | Dependency, path, Git, filesystem, or external command problem. |
Scripts should treat 3 differently from 1: it means Dalo intentionally stopped before touching state that may require review.
JSON Output Shapes
--json prints one JSON value to stdout on success. Runtime errors are printed to stderr as {"error":{"code":"...","message":"..."}} and keep the same exit code as text output. Path fields serialize as strings. Enum fields serialize as snake_case unless noted. Commands that mutate and support --dry-run include a dry_run boolean in their report.
| Command | Shape | Important fields |
|---|---|---|
init |
InitReport |
store, dry_run, operations[] with action, path, status |
target detect |
TargetDetectReport |
targets[] with id, name, support, path, exists, linked |
target link |
TargetLinkReport |
target_id, path, canonical_path, status, created_dir |
target unlink |
TargetUnlinkReport |
target_id, status |
team init |
TeamManifestMutationReport |
path, action, dry_run, resulting manifest |
team catalog add |
TeamManifestMutationReport |
path, action, catalog_id, dry_run, resulting manifest |
team catalog skills |
TeamManifestMutationReport |
path, action, catalog_id, dry_run, resulting manifest |
team catalog version |
TeamManifestMutationReport |
path, action, catalog_id, dry_run, resulting manifest |
team catalog update |
TeamCatalogUpdateReport |
catalog_id, old_version, old_commit, from_ref, candidate_commit, outcomes[], audits[], optional accepted_risk_reason, blocking_reasons[], dry_run, updated, resulting manifest |
team catalog remove |
TeamManifestMutationReport |
path, action, catalog_id, dry_run, resulting manifest |
team show |
TeamManifestView |
path, manifest |
source add |
SourceAddReport |
source, dry_run, audits[] with one AuditReport per discovered skill, optional inventory_warnings[] (code, path, message) |
source add-catalog |
SourceConfig |
id, kind, path, priority, enabled, trusted, url, update_policy, selection |
source list |
SourceListReport |
sources[], each with existing SourceConfig fields plus provenance |
source priority |
SourcePriorityReport |
source, dry_run |
source namespace <id> [<prefix>] [--clear] |
SourceNamespaceReport |
source, changed, dry_run |
source inspect |
CatalogInspectReport |
source_id, candidates[] |
source select |
CatalogSelectReport |
source_id, changed user references in added[] / removed[], complete resulting selected[], dry_run, audits[] for skills named by the operation, migration_warnings[] for degraded legacy sibling catalogs |
source refresh |
CatalogDrift |
source_id, pinned_commit, upstream_commit, outcomes[], migration_warnings[] for degraded legacy sibling catalogs |
source refresh --advance |
CatalogAdvanceReport |
exact old_lock/new_lock, selections, outcomes[], audits[], sync, blocking_reasons[], dry_run, and advanced |
source remove |
SourceRemoveReport |
source_id, checkout_path, kept_checkout, removed_approvals, removed_catalog_lock, reconciled_links[], deactivated_skills[], deactivated_instruction_packs[], cleanup_warnings[], affected_paths[], dry_run |
agent list |
AgentListReport |
resolution, inventory_warnings[], source_errors[] |
agent show |
AgentShowReport |
agent, provider compilations[] |
plan |
InstallationPlan |
schema_version, store, canonical_plugins, inventory_warnings[], tools[], hooks[], optional native_plugins[], physical destinations[] with per-target plugin/component explanations |
plugin list |
PluginListReport |
candidates[], canonical resolution |
plugin show |
PluginShowReport |
candidate, optional selected state |
plugin select / unselect / decline |
PluginMutationReport |
plugin, action, changed, dry_run |
plugin review |
PluginReviewReport |
schema_version, root_plugin, plugin_closure[], installation_plan, separately scoped decisions[], review_token, read_only |
tool list |
ToolListReport |
tools[] with exact trust/runtime/staging state, warnings[] |
tool show |
ToolStatusReport |
tool descriptor, package and source provenance, approval_value, state, optional staged_path, diagnostic |
tool audit |
ToolAuditReport |
tool, contract_hash, plugin_package_hash, passed, findings[] |
hook list |
HookListReport |
hooks[] with hook and referenced-tool states, warnings[] |
hook show |
HookStatusReport |
hook and tool contracts, package and source provenance, approval_value, tool_state, state, diagnostic |
autosync install / uninstall |
AutosyncMutationReport |
action, dry_run, resulting status |
autosync status |
AutosyncStatusReport |
configured, installed, enabled, backend, schedule, executable, store, artifacts, optional scheduler_error, optional disabled_reason, and optional last_run |
status |
StatusReport |
store, sources[] with skill_count, agent_count, and provenance, targets[], inventory_warnings[], agent_inventory_warnings[], resolution, dry-run materialization[], blocking_audits[], audit_failures[], lock, unmanaged_skills[], target_warnings[], instruction_packs[], instruction_pack_overlaps[], instruction_block_drifts[], autosync |
sync |
SyncReport |
store, dry_run, linked_targets, skill operations[], optional instruction_operations[] (source_id, pack_id, target, action, previous_commit, commit), resolution, degraded_sources[] (id, path, reason), optional inventory_warnings[] (code, path, message), optional unrefreshed_tracking_sources[], unselected_catalogs[] (source_id, available_skills) |
audit |
AuditReport |
schema_version, source_ref, skill_path, content_hash, static_engine_version, scanned_at_unix, coverage, status, optional max_severity, static_findings[], optional agent_review, optional risk_acceptance |
approve list |
ApprovalsFile |
schema_version, approvals[] |
approve skill |
audited approval outcome | audit (AuditReport), approval (ApprovalReport) |
approve agent / source / author / org |
ApprovalReport |
scope, value, action, dry_run |
approve tool / approve revoke tool |
ToolApprovalReport |
tool, content-bound approval_value, action, optional immutable staged_path, dry_run |
approve delivery / approve revoke delivery |
DeliveryApprovalReport |
skill, revision- and recipe-bound approval_value, optional generator and generator_contract_hash, providers, action, dry_run, execution (not_run during approval) |
approve hook / approve revoke hook |
HookApprovalReport |
hook, content-bound approval_value, action, dry_run |
approve revoke skill / agent / source / author / org |
ApprovalReport |
scope, value, action, dry_run |
adopt / resolve adopt |
audited adoption outcome | audit (AuditReport), adoption (AdoptReport) |
resolve list |
ResolveListReport |
unmanaged_skills[], target_warnings[], owned_skills[] |
resolve keep |
KeepReport |
skill, existing, dry_run |
resolve unkeep |
UnkeepReport |
selector, removed[], dry_run |
resolve remove-owned |
RemoveOwnedReport |
id, link_path, status |
doctor |
DoctorReport |
store, findings[], summary |
instructions enable / disable with explicit file |
InstructionPackReport |
source_id, pack_id, target, action, dry_run, optional warning |
instructions enable / disable with logical targets |
InstructionPackBatchReport |
source_id, pack_id, dry_run, de-duplicated operations[] with logical_targets[], effective target, action, optional warning |
instructions list |
InstructionPackListReport |
active_instruction_packs[] with pack_id, target, optional logical_targets[], source_id, optional commit, optional version |
Each AuditReport.static_findings[] entry contains id, severity,
category, path, optional line, message, and optional bounded evidence.
When present, risk_acceptance contains reason, accepted_at_unix, and
scope_hash; agent_review identifies the provider and isolation boundary and
includes its findings, summary, expected capabilities/actions, and undeclared
behaviors. source add and source select expose security preflight results in
their top-level audits[] arrays. source add-catalog returns only the new
SourceConfig: adding a pinned catalog does not audit anything until a skill is
selected.
Each StatusReport.audit_failures[] entry contains source_ref, source_id,
and the technical reason. The failed skill is omitted from the active
materialization plan, while the owning source is treated as degraded so an
existing owned link is not removed solely because the audit was incomplete.
Common status values:
| Field | Values |
|---|---|
TargetSupport |
supported, experimental |
TargetLinkStatus |
planned, linked, updated, existing |
TargetUnlinkStatus |
planned, unlinked, missing |
MaterializeOperationKind |
create, relink, remove, drop_record, conflict, keep, no_op |
MaterializeOperationStatus |
planned, applied, existing, blocked |
AdoptCopyStatus |
planned, copied, existing |
AdoptReplacementStatus |
planned, replaced, skipped, protected |
RemoveOwnedStatus |
planned, removed, dropped_missing, blocked_real_entry, dropped_foreign_symlink |
InstructionBlockDriftKind |
missing, malformed, stale, source_missing |
CatalogDrift.code |
new_available, selected_changed, selected_moved, selected_removed |
AutosyncRunOutcome |
running, succeeded, skipped, blocked |
TargetScanWarningCode |
unreadable_target_dir |
DoctorFinding uses:
{
"severity": "warning",
"code": "pending_approval",
"message": "human-readable diagnostic",
"next_command": "optional next command"
}
Doctor severities are error, warning, info, and ok.
SourceProvenance contains management (direct or team_manifest), optional
declared_by, credential-redacted origin_url, optional requested_ref, the
canonical resolved_commit, and the observed checkout_commit. For catalogs,
the resolved commit comes from source-lock.toml; a differing checkout commit
is preserved in output so drift remains visible.
Resolution diagnostics use these codes when present in status.resolution.diagnostics: pending_approval, local_override, shadowed, required_expanded, cross_source_require, required_blocked, legacy_bare_approval, audit_failed, and blocked_winner_alternate_available. Each JSON entry has code, a human-readable message, and optional source_ref. blocked_winner_alternate_available is advisory: its source_ref identifies the approved alternate, while required_blocked identifies the blocked winner and remains the check-blocking diagnostic. For recovery steps, see Troubleshooting and FAQ.
Store Layout
After dalo init, the store contains:
| Path | Purpose |
|---|---|
config.toml |
User-authored config: settings and source list. |
lock.toml |
Resolved user lock written by sync and instruction commands. |
state.toml |
Internal target/materialization/protection state. |
approvals.toml |
Local approval records. |
source-lock.toml |
Catalog source pins, selections, and inventory snapshots. |
autosync.toml |
Installed scheduler backend, schedule, exact paths, identifier, and artifacts. |
autosync-run.toml |
Last attempted/successful scheduled run and its durable outcome/reason. |
autosync.log, autosync-error.log |
Native scheduler stdout and stderr. |
audits/<content-hash>-<source-ref-hash>.json |
Source- and content-bound deterministic and optional agent security reports. |
.lock |
Temporary coarse lock file while mutating commands run. |
local/skills/ |
Local private skill directories. |
local/agents/ |
Local portable canonical agent packages. |
local/instructions/ |
Local instruction pack Markdown files. |
tools/ |
Immutable, approved tool closures, addressed by their exact staged content. |
generated/ |
Content-addressed generated-delivery cache; only approved derivations are promoted. |
sources/<id>/checkout/ |
Team and catalog Git checkouts. |
sources/.audit-staging/ |
Detached incoming team commits retained only while security review is required. |
Hook and plugin projection paths are created lazily, not by dalo init:
| Path | Created when |
|---|---|
hooks/, hooks/state.json |
The first native hook projection is applied; the state file records dispatcher ownership. |
plugins/, plugins/state.json |
The first native plugin projection is applied; the state file records projection ownership. |
Dalo rejects unsupported schema versions in persisted TOML files.
config.toml
Schema version: version = 1.
Example:
version = 1
[settings]
autosync = false
sync_interval = "hourly"
[[sources]]
id = "local"
kind = "local"
path = "/Users/alex/.dalo/local"
priority = 0
enabled = true
trusted = true
[[sources]]
id = "team"
kind = "team"
path = "/Users/alex/.dalo/sources/team/checkout"
priority = 10
enabled = true
trusted = true
url = "git@github.com:example/team-skills.git"
update_policy = "track"
[[sources]]
id = "public"
kind = "catalog"
path = "/Users/alex/.dalo/sources/public/checkout"
priority = 20
enabled = true
trusted = true
url = "https://github.com/example/catalog.git"
update_policy = "pin"
selection = ["review-helper"]
Fields:
| Field | Meaning |
|---|---|
settings.autosync |
Whether dalo autosync install has configured a scheduler job. |
settings.sync_interval |
Installed hourly, daily, or weekly schedule. |
sources[].id |
Stable source ID. |
sources[].kind |
local, team, or catalog. |
sources[].path |
Local filesystem path for the source root or checkout. |
sources[].priority |
Lower numbers win. |
sources[].namespace |
Optional prefix applied to every materialized skill from the source. A skill named review becomes prefix__review; the source content and source-qualified approval identity stay unchanged. |
sources[].enabled |
Disabled sources are skipped by resolution. |
sources[].trusted |
Trusted sources are approved automatically. User-added catalog sources always start untrusted. |
sources[].url |
Git URL for team/catalog sources. URLs with embedded credentials are rejected; use SSH or a credential helper. |
sources[].branch |
Optional branch label. |
sources[].update_policy |
Usually track for team sources and pin for catalog sources. |
sources[].selection |
Catalog selections by stable ID, source ref, path, or slot name. Empty for local/team sources. |
sources[].declared_by |
Team source whose dalo.toml owns this derived catalog. Generated by sync; do not edit directly. |
sources[].declared_ref |
Git version requested by the declaring team manifest. Generated by sync. |
Unknown fields are rejected.
Team repository dalo.toml
Schema version: schema_version = 1.
Team repositories may compose their checked-in skills with pinned external
catalogs. sync namespaces ordinary IDs as <team-id>.<catalog-id> and stores
the resolved commit in source-lock.toml. If either component itself contains
a dot, Dalo losslessly encodes both components into a reserved point-free
team-<hex>-catalog-<hex> ID so different declarations cannot collapse onto
the same source.
schema_version = 1
[source]
id = "company"
name = "Company Skills"
kind = "team"
[[catalog]]
id = "marketing"
url = "https://github.com/coreyhaines31/marketingskills.git"
version = "0123456789abcdef0123456789abcdef01234567"
skills = ["+copywriting", "+launch", "+seo-audit", "-seo-audit"]
priority = 11
namespace = "marketing"
Catalog fields:
| Field | Meaning |
|---|---|
id |
ID local to the manifest. The local source ID is namespaced with the team source. |
url |
Git URL. Embedded credentials are rejected. |
version |
Required Git commit, tag, or ref. ref is accepted as an alias. Immutable commits are recommended. |
skills |
Include/exclude filters. Omitted or empty means all. |
priority |
Optional global resolver priority; defaults to the team source priority plus one. |
namespace |
Optional prefix applied to every materialized skill from this catalog. |
Filter evaluation is set-based and independent of list order:
- no filters: all catalog skills
- only
-skill: all except the exclusions - any
+skillor bareskill: whitelist mode - exclusions always win over inclusions
Unknown or ambiguous filter references block sync. Manifest-derived catalogs
are untrusted by default, so their newly selected skills remain pending until a
local approval matches. source select, source priority, source remove, and
pin advancement reject derived catalogs; edit and review dalo.toml instead.
Changing a catalog URL uses an explicit two-sync replacement: remove the
declaration and sync, then add the reviewed replacement URL and sync again.
approvals.toml
Schema version: schema_version = 1.
Example:
schema_version = 1
[[approvals]]
scope = "source"
value = "team"
[[approvals]]
scope = "skill"
value = "team:review-helper"
[[approvals]]
scope = "author"
value = "team:platform-team"
Approval scopes:
| Scope | Value | Matches |
|---|---|---|
skill |
<source-id>:<slot> or <source-id>:<stable-id> |
One skill from one source. Bare slot names and bare stable IDs do not match. |
agent |
<source-id>:<name> or <source-id>:<stable-id> |
One canonical agent package from one source. |
tool |
<source-id>:<plugin>#tool:<name>@sha256:<contract-hash> |
One exact plugin-local executable contract. Approval also requires its immutable staged closure. |
delivery |
<source-id>:<slot>@id:<source-id>:<stable-id>@<commit>@sha256:<recipe-hash> |
One exact generated-delivery recipe at one source revision. Both recorded identities remain valid for revocation. |
hook |
<source-id>:<plugin>#hook:<name>@sha256:<contract-hash> |
One exact plugin-local hook contract. The referenced tool must be independently ready. |
source |
<source-id> |
Every skill from that source. |
author |
<source-id>:<owner> |
Skills from that source whose owners frontmatter contains that owner. |
org |
<source-id>:<owner> |
Same matching behavior as author; the scope is a policy label. |
Local skills and skills from trusted = true sources are approved automatically. Non-interactive commands can use existing approvals but never create new approvals.
Prefer dalo approve for all approval changes. The TOML format remains
documented for auditability and recovery, but does not need to be edited for
normal approval workflows.
lock.toml
Schema version: schema_version = 6.
This file is Dalo's resolved user lock. sync rewrites source snapshots, active skills, pending approvals, unlinked skills, and target materialization summaries. Instruction commands preserve and update active instruction-pack entries.
Top-level fields:
| Field | Meaning |
|---|---|
sources[] |
Source ID, kind, path, and optional commit. |
active_skills[] |
Skills that should be linked into targets. |
pending_approval_skills[] |
Skills blocked by approval. |
unlinked_skills[] |
Managed skills not linked, with a reason such as shadowing. |
target_materializations[] |
Last sync operations by target path. |
active_instruction_packs[] |
Instruction packs rendered into instruction files. |
Important record fields:
| Record | Fields |
|---|---|
LockedSource |
id, kind, path, optional commit |
LockedSkill |
source_ref, slot_name, optional id, source_id, source_kind, optional delivery provenance/recipe/derivation/output fingerprints, optional reason |
LockedTargetMaterialization |
link_path, optional desired_path, kind, status, optional reason |
LockedInstructionPack |
pack_id, target, optional logical_targets[], source_id, optional commit, optional version |
state.toml
Schema version: schema_version = 1.
This is internal state. Users normally inspect it through target detect, status, sync, and resolve list.
Top-level fields:
| Field | Meaning |
|---|---|
targets[] |
Logical target links with id, path, canonical_path, and enabled. |
materialization_dirs[] |
Canonical physical directories and the logical target IDs sharing each directory. |
owned_skills[] |
Symlinks Dalo owns: target_id, slot_name, link_path, store_path, plus additive delivery mode/provider/fingerprint/derivation provenance. |
protected_skills[] |
Unmanaged target slots kept by the user: target_id, slot_name. Legacy path-based entries migrate on read. |
Unknown fields in this internal state model are retained across reads and writes for downgrade safety after additive changes. Breaking changes still require a schema-version bump. User-authored configuration remains strict.
source-lock.toml
Schema version: schema_version = 3.
This file stores catalog pins and inventory snapshots. It is written by catalog selection and read by drift checks.
Top-level fields:
| Field | Meaning |
|---|---|
catalogs[] |
One CatalogLock per pinned catalog source. |
catalogs[].source_id |
Catalog source ID. |
catalogs[].commit |
Pinned commit used for the inventory snapshot. |
catalogs[].selected[] |
Selected skill references. |
catalogs[].inventory[] |
Pinned catalog entries. |
Inventory entry fields:
| Field | Meaning |
|---|---|
id |
Optional stable skill ID from frontmatter. |
slot_name |
Install slot name. |
path |
Skill directory path relative to the catalog root. |
content_hash |
Hash over skill directory content, executable file bits, and symlink metadata. |
metadata_hash |
Hash over parsed skill metadata. |
requires[] |
Declared same-source dependencies. |
SKILL.md Frontmatter
Dalo discovers a skill by finding a directory containing SKILL.md. If the file starts with YAML frontmatter fenced by --- lines, Dalo reads these fields:
---
id: review-helper
name: review-helper
description: Review pull requests for behavior regressions
owners:
- platform-team
tags:
- review
requires:
- base-style
---
# Review Helper
| Field | Required | Meaning |
|---|---|---|
id |
no | Stable skill identity. Use for catalog selections and source-qualified approvals. |
name |
no | Preferred slot name. Must be a safe slot name; otherwise Dalo falls back to the folder name and records an inventory warning. |
description |
no | Human-readable description shown in catalog inspection. |
owners[] |
no | Approval owner strings matched by author and org approvals. |
tags[] |
no | User metadata. |
requires[] |
no | Same-source or same-catalog dependencies. Required skills are expanded only when the closure is linkable and approved. |
If name is absent, the directory name is the slot name. Duplicate slot names within one source are warned and de-duplicated by resolver behavior.
SKILL.md may reference another file inside the same source checkout, but a
metadata symlink whose resolved target escapes the checkout is skipped and
reported as skipped_symlink. This keeps skill identity and approval metadata
contained within the source being scanned.
PLUGIN.toml Portable Plugins, Tools, and Hooks
Plugins are exact plugins/<name>/PLUGIN.toml packages. The top-level schema is
closed: unknown fields are rejected. schema_version = 1 and [plugin] with
name and description are required; id, version, providers,
[[plugin.members]], [[plugin.requires]], [[tool]], and [[hook]] are
optional.
schema_version = 1
[plugin]
name = "review-suite"
description = "Review helpers"
[[plugin.members]]
ref = "skill:review"
requirement = "required"
[[tool]]
schema_version = 1
id = "inspect"
entry = "bin/inspect"
runtime = "executable"
argv = []
cwd = "tool_root"
availability = "required"
[[hook]]
schema_version = 1
id = "before-shell"
tool = "inspect"
subject = "tool_call"
phase = "before"
effect = "allow_deny"
requirement = "required"
timeout_ms = 2000
failure_policy = "fail_closed"
retry = "never"
error_visibility = "model_and_user"
blocking_scope = "matched_event"
Plugin members and dependencies
Plugin members use ref, requirement (required, optional, or
recommended), and optional fallback with required kind and skill.
Members may reference skills, agents, or instructions; recommended is only
valid for instructions. A fallback is only valid for an agent member, has
kind = "inline", names a skill in skill, and that skill must also be a
required member. Dependencies use ref to a plugin with requirement
required or optional.
Tools
Tools require schema_version, id, entry, runtime (executable,
python, node), argv, cwd (tool_root), and availability (required
or optional). Optional fields are runtime_version, platforms (macos,
linux), inputs, files, env, and capabilities (filesystem_read,
filesystem_write, subprocess, or network). Tool inputs are closed name,
type (string, path, integer, boolean), and optional required
(default true) records. Paths must be plugin-root-relative and remain inside
the plugin-owned closure; Dalo stages and hashes that closure before approval.
Hooks
Hooks are closed descriptors. They require schema_version, id, tool,
subject, phase, effect, requirement, timeout_ms, failure_policy,
retry, error_visibility, and blocking_scope; matcher, bindings, and
fallback are optional fields. tool references the same-plugin tool.
subject is session, user_prompt, tool_call, or workflow; phase is
before, after, end, or completion_attempt; effect is observe,
add_context, allow_deny, rewrite_input, replace_output, or
continue_workflow. requirement is
required or optional; failure_policy is fail_open, fail_closed, or
report; retry is only never; error_visibility is user or
model_and_user; and blocking_scope is only matched_event.
matcher.tool_names is an optional unique exact provider-tool-name list and is
valid only when subject = "tool_call".
Bindings are closed input/field records and map a lower-snake tool input to
one admitted event field: session.id, session.cwd,
session.permission_mode, actor.kind, actor.id, transcript.path,
session.end_reason, prompt.text, tool.call_id, tool.name,
workflow.already_continued, or workflow.last_message. Required hooks have
no fallback; optional hooks use the fallback value omit explicitly as
fallback = "omit" when omitted
behavior is intended. The subject/phase/effect combination must have a
verified mapping in at least one supported provider. fail_closed is valid
only for a before pre-action enforcement effect (allow_deny or
rewrite_input) or completion_attempt plus continue_workflow; observe
and replace_output require failure_policy = "report". A binding's field
must be available for the selected subject and phase. IDs are lower kebab-case, input names are lower
snake-case, timeout_ms is 100 through 120000, and each matcher or binding
list holds at most 256 entries. Hooks reference a same-plugin tool and are
independently approved; malformed, unknown, unsafe, or unsupported contracts
are blocked.
DELIVERY.toml Provider Builds
Direct delivery remains the default: without a DELIVERY.toml, Dalo links the
discovered skill directory unchanged to every target.
A logical skill can instead select existing, provider-specific build artifacts from the same pinned source checkout:
schema_version = 1
kind = "prebuilt"
universal_fallback = false
[providers]
codex = ".agents/skills/impeccable"
claude = ".claude/skills/impeccable"
cursor = ".cursor/skills/impeccable"
Provider paths are relative to the source checkout. Each artifact must be a
real directory inside that checkout, contain SKILL.md, and contain no
symlinks or special filesystem entries. Dalo fingerprints every artifact,
audits it, and links the matching artifact for each logical target. Artifact
directories referenced by a delivery manifest are not inventoried again as
independent logical skills. The provider ID universal is reserved for the
canonical artifact selected by universal_fallback and cannot be declared in
the providers table.
An omitted provider mapping blocks that target. Set universal_fallback = true
only when the logical skill directory is intentionally valid for every unmapped
provider. When multiple logical targets share one physical target directory,
their selected artifact must be identical; otherwise Dalo reports a conflict
instead of choosing one implicitly.
sync, status, and doctor expose delivery selections in JSON. Human-readable
sync and status output lists prebuilt selections and blocked mappings. The
user lock records the manifest, provider paths, and fingerprints; changing a
provider artifact therefore appears as skill_delivery_changed lock drift.
Audit reports use provider-qualified selectors such as
dalo audit impeccable:impeccable@codex, so findings, risk acceptance, and
persisted provenance stay bound to the exact provider artifact.
A generated delivery requires a stable skill frontmatter id, declares a
same-source plugin tool, and names the relative output directory expected for
each provider:
schema_version = 1
kind = "generated"
generator = "company:builder#tool:build"
output_input = "output_dir"
[providers]
codex = "codex/review"
claude = "claude/review"
The referenced tool must be required, declare filesystem_write, and expose
the named required path input in its argument contract. The delivery
manifest, plugin manifest, and every file in the tool closure must be tracked
by the same clean Git source commit. Dalo binds the recipe fingerprint to that
commit and the exact tool contract. Generated delivery schema v1 requires the
tool runtime to be executable; Python and Node runtime lookup is rejected so
sync never selects an interpreter from its ambient PATH. An executable script
must use an absolute shebang such as #!/bin/sh; /usr/bin/env shebangs are
rejected for the same reason. Generated execution also rejects a declared
PATH environment input and sets PATH to the empty string, so scripts must
not resolve subprocesses through the invoking user's environment.
Generator execution is fail-closed behind an operating-system filesystem sandbox inherited by every descendant: Linux uses a fully enforced Landlock ABI v3 domain, while macOS uses the system Seatbelt launcher. The sandbox permits filesystem writes only below the one delivery staging directory. If the required sandbox cannot be fully enforced, Dalo does not run the generator.
Generated delivery has two independent approvals:
dalo approve delivery company:review
dalo approve tool company:builder#tool:build
The first approves only the exact revision-bound recipe; the second approves
the generator tool contract. A new source commit or changed recipe invalidates
the recipe approval. The approval key records both the current slot and the
required stable ID, so stale trust remains revocable after a rename, deletion,
or invalid recipe through either historical identity. Approval itself remains
inert. Once both exact approvals exist, a real sync invokes the immutable
staged tool closure with an empty environment except for explicitly declared
variables. Dalo passes a newly created staging directory as the declared output
input, enforces a bounded runtime and output tree, rejects undeclared paths,
symlinks, multiply linked or special files, oversized output, and
source-checkout changes. Surviving members of the generator process group are
terminated before Dalo copies the validated output into a fresh-inode snapshot.
Dalo audits that snapshot, promotes it, and verifies and audits the immutable
cache path again before it can reach materialization. The source commit and
cleanliness are rechecked after that final cache verification, immediately
before materialized state is persisted, and again immediately before the user
lock commit. Source drift during generation therefore rolls back activation and
prevents provenance from being committed. Blocking findings or a failed
generator leave the last known-good target link unchanged.
Successful output is made read-only and atomically promoted below
generated/sha256/<derivation-hash>. The derivation identity binds the logical
skill, source commit, recipe, and exact tool contract; subsequent syncs verify
and reuse that cache instead of executing again. Only after verification does
the normal transactional materializer link provider outputs. Dry-run, JSON,
status, and doctor expose miss, generated, or hit cache state,
derivation identity, selected output fingerprint, and any blocking remediation.
AGENT.md Canonical Packages
An agent package is an agents/<name>/AGENT.md directory. AGENT.md starts
with YAML frontmatter and then contains the portable Markdown prompt. Required
fields are schema_version: 1, name, and description; model.profile,
targets, and skills express portable intent and requirements.
---
schema_version: 1
name: reviewer
description: Reviews pull requests for behavior regressions
model:
profile: balanced
targets: [claude, codex]
skills: [review-helper]
---
Review behavior before style nits.
targets may omit providers (all compatible providers) or name claude and
codex; skills lists required skill references. Optional id, owners,
tags, tools, filesystem, network, and providers metadata add identity,
boundaries, and provider overlays. Packages are bounded to 256 entries, 16
directory levels, and 16 MiB total; AGENT.md itself is limited to 1 MiB.
Symlinks and unsupported special files are rejected.
Instruction Packs
Instruction packs are Markdown files in local/instructions/<id>.md or
<source>/instructions/<id>.md. Dalo discovers both locations. Bare IDs select
local packs; source packs use an explicit source-qualified reference such as
company:engineering-defaults. Pack IDs use the same safe token rule as source
IDs: letters, digits, ., _, and -, excluding . and ...
Local managed-block markers retain their existing bare pack ID. Source-backed
markers use the full source-qualified reference, allowing same-named packs from
different sources to coexist in one instruction file. Source-backed lock entries
bind the activation to the exact clean Git commit. If that checkout advances,
normal dalo sync refreshes only packs already present in the user lock and
updates their commit and version provenance. Newly discovered packs remain
inactive. Refresh requires the source to remain trusted or source-approved and
the existing managed block to match the previously rendered immutable commit.
Revoked approval, dirty or missing sources, missing Git history, untracked pack
files, malformed markers, and externally edited managed blocks fail closed with
an actionable error instead of overwriting the target. Tracking team sources
advance through normal sync; catalog sources retain their explicit pinned
advancement workflow.
Dalo reads an optional version: entry from the first five lines and optional
topics: or tags: metadata from the first eight lines:
version: 1.0.0
topics: review, formatting
# Team Style
Use concise review comments.
tags: can be used instead of topics:. Topics are comma-separated and are used for advisory overlap warnings when multiple active packs share topics.
Managed blocks use these markers:
<!-- dalo:start team-style -->
...
<!-- dalo:end team-style -->
Dalo only rewrites bytes inside the pack's own managed block. Content outside managed blocks is preserved.
Source: docs/reference.md