Introduction

Declarch is a declarative wrapper for many package managers.

Short version:

  • you list what you want,
  • declarch maps it to backends,
  • declarch sync applies it.

Why people use it

  • One workflow for mixed ecosystems (pacman, flatpak, npm, nix, etc).
  • Config-first style that is easier to review and version.
  • Backend configs are flexible, so they can follow upstream package-manager changes.

What it is not

  • Not a replacement for every backend CLI feature.
  • Not guaranteed perfect on every backend/environment pair yet.

v0.8 note

v0.8 introduced breaking changes. If you are migrating, back up config first and start with preview.

cp -r ~/.config/declarch ~/.config/declarch.backup
declarch --dry-run sync

Path above is Linux-style. Use this to print real paths on your OS:

declarch info --doctor

One important behavior

declarch install expects explicit backend now. Use backend:package or --backend <name>.

Start here

  1. Installation
  2. Quick Start
  3. Basic Concepts

Installation

Pick one method.

Arch Linux (AUR)

paru -S declarch-bin
# or
yay -S declarch-bin

Linux/macOS (install script)

curl -sSL https://raw.githubusercontent.com/nixval/declarch/main/install.sh | sh

After install, it runs lightweight smoke checks (--help, info).

Do this for each of distro for easy to githubusercontent

decl init --backend aur paru yay pacman // for Arch distro base
decl init --backend nala apt // for Debian/ubuntu distro base
decl init --backend dnf5 // for Red Hat distro base
decl init --backend zypper // for SUSE distro base
decl init --backend brew // for macOS

// or you can custom it based on package manager preference
// I already manage it at nixval/package-manager
// or see the list at `decl init --list backend`

Windows (PowerShell, alpha preview)

irm https://raw.githubusercontent.com/nixval/declarch/main/install.ps1 | iex

Current status: alpha preview. After install, it runs lightweight smoke checks (--help, info). Still dont have the configuration, but possibly can configured to have winget, choco, scoop, etc.

Manual binary install

wget https://github.com/nixval/declarch/releases/latest/download/declarch-x86_64-unknown-linux-gnu.tar.gz
tar xzf declarch-x86_64-unknown-linux-gnu.tar.gz
sudo install declarch /usr/local/bin/

Build from source

cargo install declarch --git https://github.com/nixval/declarch

Source builds can be slower on first run because Cargo compiles the full dependency graph. If you want a faster setup path, prefer prebuilt release binaries via install script or package manager.

Verify

declarch --version
declarch --help
declarch info --doctor -v

Next: Quick Start

Quick Start

0) Understand the flow first (declarative)

Declarch works best when you treat KDL config as source of truth.

  1. Declare packages in module files.
  2. Preview with dry-run.
  3. Apply with sync.
declarch --dry-run sync
declarch sync

1) Initialize

declarch init

Expected structure:

~/.config/declarch/
├── declarch.kdl
├── backends/
└── modules/
    └── base.kdl

Use this anytime to see actual config/state paths on your OS:

declarch info --doctor -v

2) Adopt backend(s) first

# Arch-based
declarch init --backend aur,paru,yay,pacman

# Debian/Ubuntu
declarch init --backend nala,apt

# Fedora/RHEL
declarch init --backend dnf5

# SUSE
declarch init --backend zypper

# macOS
declarch init --backend brew

# discover options from registry
declarch init --list backends
declarch init --list modules

3) Add packages (declarative first)

Example module file (~/.config/declarch/modules/mydotfiles.kdl):

meta {
    title "My dotfiles"
}

pkg {
    aur { hyprland waybar }
    flatpak { firefox }
    soar { gimp }
    npm {
        @opencode-ai/sdk
        oh-my-opencode
    }
}

Edit flow:

declarch edit
declarch edit mydotfiles --create
declarch edit mydotfiles

Then:

declarch --dry-run sync
declarch lint --fix
declarch sync prune
declarch sync

4) Direct install (optional shortcut)

declarch install aur:bat aur:fzf aur:ripgrep
declarch install npm:typescript
declarch install bat fzf ripgrep --backend aur

This writes package entries to modules/others.kdl automatically.

5) Add more backends when needed

declarch init --backend npm
declarch init --backend pnpm,yarn
# also valid
declarch init --backend pnpm yarn

That is the core workflow.

First Run (Linear Guide)

Use this if you want one straight path from zero to first successful sync.

1) Install declarch

Choose one method from Installation, then verify:

declarch --version
declarch --help

2) Initialize config

declarch init

If you are unsure where files are created on your OS:

declarch info --doctor

3) Add packages

Declarative-first path (recommended):

// ~/.config/declarch/modules/base.kdl
pkg {
    aur { bat fd ripgrep }
    npm { typescript }
}

Then apply with preview:

declarch --dry-run sync
declarch sync

Direct install shortcut (still valid):

declarch install aur:bat aur:fd aur:ripgrep
declarch install npm:typescript
// check it at `decl edit others`

Alternative: use one backend for all packages in a command:

declarch install bat fzf ripgrep --backend aur

4) Preview changes

declarch --dry-run sync

Review what will be installed/adopted/removed.

5) Apply

declarch sync

6) First troubleshooting loop

If a command fails, run this sequence:

declarch lint --mode validate
declarch info --doctor
declarch --dry-run sync

Then check Troubleshooting for targeted fixes.

Common Mistakes

1) Forgetting backend prefix on install

Symptom:

  • package lands in unexpected backend block, or
  • install command fails validation.

Fix:

declarch install aur:bat
# or
declarch install bat --backend aur

2) Running sync directly on first setup

Symptom:

  • unexpected changes, or confusion about what will happen.

Fix: always preview first.

declarch --dry-run sync
declarch sync

3) Backend configured but binary not installed

Symptom:

  • errors like Package manager error: <binary> not found.

Fix:

declarch info <nameofthebackend>
// example
declarch info aur

Install missing binary or temporarily remove/disable that backend.

4) Editing KDL without validation

Symptom:

  • parse error at sync/lint time.

Fix:

declarch lint --mode validate

5) Confusing config path vs state path

Symptom:

  • editing one file while declarch reads another path.

Fix:

declarch info --doctor -v

Use the reported paths as source of truth.

6) Trying too many advanced flags at once

Symptom:

  • hard to debug whether issue is from profile/host/modules/hooks.

Fix:

  • start with plain declarch --dry-run sync
  • add one flag at a time (--profile, then --host, then modules)

Config Progression (Minimal -> Advanced)

This page shows a practical progression for you to start small and scale safely.

Stage 1: Minimal

declarch.kdl

imports {
    "modules/base.kdl"
}

modules/base.kdl

pkg {
    aur {
        git
        neovim
    }
}

Use this stage to validate your first workflow:

declarch --dry-run sync
declarch sync

Stage 2: Add second backend

modules/base.kdl

pkg {
    aur {
        git
        neovim
    }
    npm {
        typescript
        pnpm
    }
}

Stage 3: Split by purpose (modular)

declarch.kdl

imports {
    "modules/base.kdl"
    "modules/development.kdl"
}

modules/development.kdl

pkg {
    cargo {
        ripgrep
        fd-find
    }
    npm {
        eslint
        prettier
    }
}

Stage 4: Advanced targeting (profile/host)

Use profile/host blocks for machine-specific or role-specific packages.

Example concept:

profile "work" {
    pkg {
        npm { @angular/cli }
    }
}

host "laptop-1" {
    pkg {
        flatpak { com.discordapp.Discord }
    }
}

Activate with:

declarch sync --profile work --host laptop-1

Rule of thumb

  • Keep base.kdl stable and small.
  • Add new modules only when package groups become hard to scan.
  • Introduce profile/host targeting only after base + modules are clear.

Basic Concepts

1) Declarch is a wrapper

Declarch orchestrates real package managers. You are still using actual tools under the hood (apt, pacman, flatpak, npm, nix, etc).

2) Agnostic design

You can mix ecosystems in one config:

pkg {
    pacman { firefox git }
    flatpak { org.mozilla.firefox }
    npm { typescript }
}

3) Declarative loop

  1. declare packages
  2. run sync
declarch sync

4) Keep config portable first

If you copy your config to another machine (laptop, VPS, etc), it should still work with default sync:

declarch sync

No host or profile required. but if you want specify host and profile you can configure it.

5) Backend configs can evolve

Package managers change over time. Declarch backend definitions are designed to be editable and update-friendly.

6) Modules keep things simple

Use small files by context:

  • base.kdl
  • dev.kdl
  • work.kdl
  • gaming.kdl

7) Optional profile/host layering

If you need machine-specific extras, you can opt in:

profile "work" {
    pkg {
        npm { @angular/cli }
    }
}

host "laptop-1" {
    pkg {
        flatpak { com.discordapp.Discord }
    }
}


```bash
declarch sync --profile work
declarch sync --host laptop-1

If you do not pass those flags, declarch uses your normal default config only.

8) Start safe

When unsure, use:

declarch --dry-run sync

Cross-OS (Alpha)

Declarch is designed to stay backend-agnostic, but cross-OS support is still in progress.

Current status:

  • Linux: most tested path
  • macOS: alpha preview
  • Windows: alpha preview

This is still usable for early testing. Start with preview/doctor first.

Quick safety flow

declarch info --doctor
declarch --dry-run sync

info --doctor prints the actual config/state paths for your current OS.

Paths by OS

Declarch uses platform-native directories via Rust ProjectDirs.

Typical examples:

  • Linux config: ~/.config/declarch
  • macOS config: ~/Library/Application Support/declarch
  • Windows config/state: under %APPDATA% / %LOCALAPPDATA% equivalents (platform/runtime-dependent)

Use declarch info --doctor for exact paths on your machine.

Why this still works

  • If a backend is not available for your OS, declarch warns and skips.
  • Your config stays declarative and portable.
  • You can still run the same declarch sync flow on different machines.

Roadmap direction

  • Better Windows backend coverage (winget, choco, scoop) is planned.
  • More macOS validation (brew + mixed backends) is planned.
  • Warnings are designed to stay clear and easy to use.

Commands

This page maps current CLI behavior (declarch --help) into one practical guide.

Declarative-first mindset

Declarch is designed to be config-first:

pkg {
    aur { bat fzf ripgrep }
    npm { typescript }
}

Then apply:

declarch --dry-run sync
declarch sync

You can still use install for speed, but your source of truth stays in KDL modules.

Global flags (all commands)

  • -v, --verbose
  • -q, --quiet
  • -y, --yes
  • -f, --force
  • --dry-run
  • --format table|json|yaml
  • --output-version v1 (for machine output contracts)

init

Usage:

declarch init [OPTIONS] [SOURCE]

Main usage:

declarch init
declarch init --backend npm
declarch init --backend apt,nala
declarch init --list backends
declarch init --list modules

SOURCE supports:

  • user/repo
  • user/repo:variant
  • user/repo/branch
  • gitlab.com/user/repo
  • https://...kdl
  • registry module name (example: desktop/hyprland)

Important options:

  • --backend <NAME>...
  • --list <backends|modules>
  • --local (create local module, skip registry lookup)
  • --host <NAME>
  • --restore-declarch

install

Usage:

declarch install [OPTIONS] <PACKAGES>...

Examples:

declarch install aur:bat aur:fzf aur:ripgrep
declarch install npm:typescript
declarch install bat fzf ripgrep --backend aur
declarch install firefox --module browsers --backend aur

Options:

  • -b, --backend <BACKEND>
  • -m, --module <MODULE>
  • --no-sync

sync

Usage:

declarch sync [OPTIONS] [SUBCOMMAND]

Common flow:

declarch --dry-run sync
declarch sync

Core options (default sync + update + prune):

  • --target <TARGET>
  • --profile <NAME>
  • --host <NAME>
  • --diff
  • --noconfirm
  • --hooks
  • --modules <MODULES>

Subcommands:

declarch sync update
declarch sync prune
declarch sync cache --backend npm
declarch sync upgrade --backend npm --no-sync

Subcommand-specific options:

  • sync cache: -b, --backend <BACKEND>...
  • sync upgrade: -b, --backend <BACKEND>..., --no-sync

Hook behavior and gating details are documented in: Policy, Hooks, and Editor Behavior.

Usage:

declarch search [OPTIONS] <QUERY>

Examples:

declarch search firefox
declarch search firefox -b aur,flatpak
declarch search npm:typescript
declarch search firefox --installed-only
declarch search firefox --available-only
declarch search firefox --local
declarch search firefox --limit all

Options:

  • -b, --backends <BACKENDS>
  • --limit <NUM|all|0>
  • --installed-only
  • --available-only
  • --local

info

Usage:

declarch info [OPTIONS] [QUERY]

Modes/examples:

declarch info
declarch info --doctor
declarch info --plan
declarch info --list
declarch info --list --scope all
declarch info --list --scope orphans
declarch info --list --scope synced
declarch info --list --scope unmanaged
declarch info aur:bat

Options:

  • --doctor
  • --plan
  • --list
  • --scope all|orphans|synced|unmanaged
  • --backend <BACKEND>
  • --package <PACKAGE>
  • --profile <NAME>
  • --host <NAME>
  • --modules <MODULES>

lint

Usage:

declarch lint [OPTIONS]

Examples:

declarch lint
declarch lint --mode validate
declarch lint --mode duplicates
declarch lint --mode conflicts --backend aur
declarch lint --diff
declarch lint --fix
declarch lint --strict
declarch lint --benchmark

State-related options:

declarch lint --repair-state
declarch lint --state-rm soar:firefox
declarch lint --state-rm package --state-rm-backend soar
declarch lint --state-rm-backend soar --state-rm-all

Main options:

  • --mode all|validate|duplicates|conflicts
  • --backend <BACKEND>
  • --diff, --fix, --strict, --benchmark
  • --repair-state
  • --state-rm <IDS>
  • --state-rm-backend <BACKEND>
  • --state-rm-all
  • --profile <NAME>
  • --host <NAME>
  • --modules <MODULES>

edit

Usage:

declarch edit [OPTIONS] [TARGET]

Examples:

declarch edit
declarch edit mydotfiles --create
declarch edit mydotfiles --preview --number
declarch edit mydotfiles --validate-only
declarch edit mydotfiles --backup

Options:

  • -p, --preview
  • --number (requires --preview)
  • -c, --create
  • --auto-format
  • --validate-only
  • -b, --backup

Editor resolution policy details: Policy, Hooks, and Editor Behavior.

switch

Usage:

declarch switch [OPTIONS] <OLD_PACKAGE> <NEW_PACKAGE>

Examples:

declarch switch neovim neovim-git
declarch switch firefox aur:firefox-nightly --backend aur
declarch switch firefox firefox-nightly --dry-run

Options:

  • --backend <BACKEND>

Hidden/internal commands

Not shown in main help, but available for advanced/internal workflows:

  • declarch self-update (script/manual install update path)
  • declarch completions <shell>
  • declarch ext

KDL Basics

Declarch config is written in KDL. This page only covers beginner syntax.

Minimal example

pkg {
    pacman {
        firefox
        git
    }
}

Rules to remember

  1. Blocks use {}.
  2. Package names are plain entries inside backend blocks.
  3. Quote string values in metadata/settings fields.
meta {
    title "My Setup"
    description "My daily packages"
}

Typical layout

imports {
    "modules/base.kdl"
    "modules/dev.kdl"
}

pkg {
    pacman { firefox }
    flatpak { org.mozilla.firefox }
    npm { typescript }
}

Optional profile and host blocks

Use this only when you want extra packages for a specific situation. If you do not use these blocks, nothing changes in default behavior.

pkg {
    aur { git curl }
}

profile "desktop" {
    pkg {
        aur { hyprland waybar }
    }
}

host "vps-1" {
    pkg {
        aur { fail2ban tmux }
    }
}

Activate them explicitly from CLI:

declarch sync --profile desktop
declarch sync --host vps-1
declarch sync --profile desktop --host vps-1

Need full syntax details? Use Syntax Reference (Advanced).

Backends

Backends are how declarch talks to package managers.

Think of it like this:

  • declarch is the coordinator,
  • backends do the real package operations.

Default + adopt model

  • declarch init creates default backend definitions.
  • declarch init --backend <name> adopts extra backends from registry.
  • Local backend files are editable.

Common backend groups

  • System: aur, pacman, flatpak, apt, nala, dnf, snap, nix, brew
  • Language/dev: npm, pnpm, yarn, bun, cargo, pip, gem, go
  • Other: soar

Planned Windows backends: winget, choco, scoop.

Add backend definitions

declarch init --backend npm
declarch init --backend pnpm,yarn
declarch init --backend pnpm yarn

Use backends in package config

pkg {
    pacman { firefox }
    flatpak { org.mozilla.firefox }
    npm { typescript }
    nix { nil }
}

Fallback concept

A backend can fallback when binary is missing. Examples:

  • nala -> apt
  • aur -> pacman (when no AUR helper is available)
  • paru -> pacman
  • yay -> pacman

Beginner tips

  • Start small.
  • Add one backend at a time.
  • Keep backend files versioned in git.
  • Sharing one config across laptop/VPS is okay.
  • If a backend is not for your current OS, declarch will skip it and continue.

Modules

Modules help keep config readable.

Why modules?

Instead of one huge file, split by purpose:

base.kdl
dev.kdl
work.kdl
gaming.kdl

Create one

Beginner path (recommended):

declarch edit --create dev

Manual path (Linux example):

mkdir -p ~/.config/declarch/modules
cat > ~/.config/declarch/modules/dev.kdl << 'EOKDL'
pkg {
    aur {
        neovim
        tmux
    }

    npm {
        typescript
    }
}
EOKDL

For macOS/Windows exact config path, check:

declarch info --doctor

Import it

imports {
    "modules/base.kdl"
    "modules/dev.kdl"
}

Template

meta {
    title "Dev"
    description "Development tools"
}

pkg {
    aur {
        // packages here
    }
}

Practical tips

  1. One module = one context.
  2. Use obvious names.
  3. Keep each module short.

Minimal Setup

Smallest useful setup for beginners.

declarch.kdl

imports {
    "modules/base.kdl"
}

modules/base.kdl

pkg {
    aur {
        neovim
        git
    }
}

Apply

declarch --dry-run sync
declarch sync

Why this is a good start

  • only one module
  • easy to read
  • easy to expand later

Desktop Example

Simple desktop-oriented module layout.

Suggested structure

modules/
├── base.kdl
├── desktop.kdl
└── apps.kdl

modules/base.kdl

pkg {
    aur {
        neovim
        bat
        fzf
        ripgrep
    }

    pacman {
        git
        curl
        wget
    }
}

modules/desktop.kdl

pkg {
    aur {
        hyprland
        waybar
        rofi-wayland
    }

    pacman {
        foot
        mako
        grim
        slurp
    }
}

modules/apps.kdl

pkg {
    pacman {
        firefox
        thunderbird
    }

    flatpak {
        com.spotify.Client
        org.telegram.desktop
    }
}

declarch.kdl

imports {
    "modules/base.kdl"
    "modules/desktop.kdl"
    "modules/apps.kdl"
}

Apply safely

declarch --dry-run sync
declarch sync

Development Example

Beginner-friendly dev setup with separate modules.

Prerequisite

declarch init --backend npm

Structure

modules/
├── base.kdl
├── dev.kdl
└── langs.kdl

modules/dev.kdl

pkg {
    aur {
        neovim
        tmux
        docker
    }

    pacman {
        git
        github-cli
        jq
    }
}

modules/langs.kdl

pkg {
    aur {
        rustup
    }

    npm {
        typescript
        ts-node
        prettier
        eslint
    }
}

declarch.kdl

imports {
    "modules/base.kdl"
    "modules/dev.kdl"
    "modules/langs.kdl"
}

Apply

declarch --dry-run sync
declarch sync

Modular Example

Organize by purpose, not by backend.

Example structure

modules/
├── core.kdl
├── work.kdl
├── gaming.kdl
└── media.kdl

core.kdl

pkg {
    aur {
        neovim
        bat
        fzf
    }

    pacman {
        git
        curl
    }

    flatpak {
        org.mozilla.firefox
    }
}

work.kdl

pkg {
    pacman {
        slack-desktop
        zoom
    }

    flatpak {
        com.microsoft.Teams
    }
}

Select imports per machine

// work laptop
imports {
    "modules/core.kdl"
    "modules/work.kdl"
}
// gaming pc
imports {
    "modules/core.kdl"
    "modules/gaming.kdl"
    "modules/media.kdl"
}

Why this pattern works

  • cleaner diffs
  • easier reuse
  • machine-specific setups stay simple

Syntax Reference (Advanced)

Technical reference for KDL structures used by declarch.

If you are new, read:

Core blocks

meta { ... }
imports { ... }
pkg { ... }

Package declarations

Preferred (nested)

pkg {
    pacman { firefox git }
    flatpak { org.mozilla.firefox }
    npm { typescript }
}

Also accepted (compatibility)

pkg:pacman { firefox git }

pkg {
    pacman:firefox
    npm:typescript
}

Optional advanced blocks

Backend options override

options:pacman {
    noconfirm_flag "--noconfirm"
}

Env override

env:global {
    "http_proxy=http://127.0.0.1:8080"
}

env:npm {
    "NPM_CONFIG_REGISTRY=https://registry.npmjs.org"
}

Package source overrides (backend-specific)

repos:pacman {
    "core"
    "extra"
}

Hooks

hooks {
    pre-sync "echo before"
    post-sync "echo after"
}

To execute hooks, users must opt in:

experimental {
    "enable-hooks"
}

And run sync with --hooks.

Policy

policy {
    protected "linux" "systemd"
    orphans "ask"
    require_backend "true"
    forbid_hooks "false"
    on_duplicate "warn"
    on_conflict "warn"
}

MCP policy (optional)

Default behavior is read-only for MCP actions. Enable write tools only when you explicitly trust your MCP client flow.

mcp {
    mode "write-enabled"
    allow_tools "declarch_sync_apply"
}

Profile and host blocks

These are optional overlays and are inactive by default.

profile "desktop" {
    pkg { aur { hyprland waybar } }
}

host "vps-1" {
    pkg { aur { fail2ban } }
}

Use from CLI:

  • declarch sync --profile desktop
  • declarch sync --host vps-1

Validation notes

  • Keep beginner config in nested pkg style unless migration requires compatibility syntax.
  • Unknown keys may be ignored in some contexts for forward compatibility.
  • Use declarch lint --mode validate after manual edits.

Custom Backends (Advanced)

This page documents custom backend authoring for backends/*.kdl under your declarch config directory.

File placement and import

  1. Create file (Linux example):
mkdir -p ~/.config/declarch/backends
$EDITOR ~/.config/declarch/backends/mypm.kdl

Use declarch info --doctor to print your exact config path on current OS.

  1. Import in declarch.kdl:
backends {
    "backends/mypm.kdl"
}

Minimal valid backend

backend "mypm" {
    binary "mypm"

    list "{binary} list" {
        format "whitespace"
        name_col 0
        version_col 1
    }

    install "{binary} install {packages}"
    remove "{binary} remove {packages}"
}

Required and optional fields

Required

  • backend "name" { ... }
  • binary "..." (single or multiple)
  • install "...{packages}..."
  • list "..." { ... } for state/introspection
  • remove "...{packages}..."
  • search "...{query}..." { ... }

Optional commands

  • search_local "...{query}..." { ... }
  • update "..."
  • upgrade "..."
  • cache_clean "..."
  • noconfirm "-y"
  • needs_sudo true
  • fallback "other-backend"
  • env KEY="VALUE"

"-" can be used on some commands to explicitly disable capability.

meta {
    title "My Backend"
    description "What this backend does"
    kdl-maintainer "your-name"
    tags "linux" "package-manager"
    homepage "https://example.com"
    platforms "linux"
    requires "mybinary"
    install-guide "https://example.com/install"
}

Compatibility:

  • Canonical metadata keys: kdl-maintainer, install-guide
  • Legacy metadata aliases: maintainer, maintained, installation_guide

Placeholders

  • {binary}: resolved executable (supports multi-binary and fallback scenarios)
  • {packages}: space-separated package arguments
  • {query}: search query text

If binary has multiple options, include {binary} in command templates.

Output format parsers

Supported format values:

  • whitespace
  • tsv
  • json
  • json_lines / jsonl / ndjson
  • npm_json
  • json_object_keys
  • regex

Whitespace example

list "{binary} -Q" {
    format "whitespace"
    name_col 0
    version_col 1
}

JSON example (nested path)

list "{binary} list --json" {
    format "json"
    json {
        path "dependencies"
        name_key "name"
        version_key "version"
    }
}

Compatibility note: flat keys (json_path, name_key, version_key) are also accepted.

Search JSON example

search "{binary} search {query} --json" {
    format "json"
    json {
        path "results"
        name_key "name"
        version_key "version"
        desc_key "description"
    }
}

Regex example

search "{binary} search {query}" {
    format "regex"
    regex "^([^\s]+)\s+-\s+(.+)$"
    name_group 1
    desc_group 2
}

Validation expectations

Backend validation enforces:

  • install must include {packages}
  • remove (if set) must include {packages}
  • search/search_local (if set) should include {query}
  • parser-specific required keys must exist (e.g. name_key for JSON list)

Fallback example

backend "nala" {
    binary "nala"
    fallback "apt"

    list "{binary} list --installed" {
        format "regex"
        regex "^(\S+)/"
        name_group 1
    }

    install "{binary} install -y {packages}"
    remove "{binary} remove -y {packages}"
    needs_sudo true
}

Testing checklist

# parse + config checks
declarch lint --mode validate

# backend visibility
declarch info

# optional search smoke test
declarch search mypm:foo --limit 5

Then run a limited dry-run sync:

declarch --dry-run sync --target mypm

Publishing

If backend works across environments, contribute to:

  • https://github.com/nixval/declarch-packages

Debugging

This page is a practical troubleshooting playbook for config, state, and backend behavior.

Quick triage

Run these first:

declarch info --doctor
declarch info --list --scope all
declarch lint
declarch --dry-run sync

What this gives you:

  • info --doctor: runtime/config/state health checks
  • info --list --scope all: everything tracked in state
  • lint: config and consistency warnings
  • --dry-run sync: planned install/adopt/prune actions before mutation

Lint for debugging (soft checks)

Use lint modes to isolate problem type quickly:

# syntax/import/basic structure
declarch lint --mode validate

# duplicate declarations
declarch lint --mode duplicates

# known config conflicts
declarch lint --mode conflicts

# inspect planned drift from current state
declarch lint --diff

# safe automatic cleanup
declarch lint --fix

# strict CI-like mode (warnings fail)
declarch lint --strict

# state structure repair only
declarch lint --repair-state

Helpful filters:

declarch lint --mode conflicts --backend aur
declarch lint --mode duplicates --backend flatpak

Info for debugging

Use info to explain state and scope:

# full tracked state
declarch info --list --scope all

# only unmanaged installed packages
declarch info --list --scope unmanaged

# backend focus
declarch info --list --scope all --backend soar

# package-focused status/reasoning
declarch info firefox
declarch info --package firefox

State mismatch (safe fix, no uninstall)

Use when sync shows unexpected Adopt, wrong backend mapping, or stale entries.

1) Preview

declarch lint --state-rm soar:firefox --dry-run

2) Remove from state

declarch lint --state-rm soar:firefox

3) Verify

declarch info --list --scope all --backend soar
declarch --dry-run sync

Common state remove patterns:

# exact id
declarch lint --state-rm backend:package

# plain name in one backend
declarch lint --state-rm package --state-rm-backend backend

# remove all entries for one backend
declarch lint --state-rm-backend backend --state-rm-all

Search debugging tips

# backend-specific search
declarch search soar:firefox
declarch search firefox --backends soar

# local installed scan only
declarch search firefox --local

# managed-only check (declarch state)
declarch search firefox --installed-only

Use --verbose when you need backend timing/error details.

Suggested workflow

declarch info --doctor
declarch lint --mode validate
declarch lint --diff
declarch --dry-run sync

If the plan still looks wrong, use targeted state cleanup (--state-rm*) and re-run dry-run sync.

Notes

  • --state-rm* only changes declarch state; it does not uninstall packages.
  • If package name is ambiguous across backends, use backend:package.
  • Add -y for non-interactive runs.

Remote Init (Advanced)

Use this page when you want to initialize config from a remote source.

Supported source forms

user/repo
user/repo:variant
user/repo/branch
gitlab.com/user/repo
https://example.com/path/declarch.kdl
registry/module

Resolution behavior

GitHub shorthand

declarch init username/dotfiles

Resolves to repository default branch and fetches declarch.kdl.

Variant

declarch init username/dotfiles:minimal

Targets variant config (e.g. declarch-minimal.kdl).

Branch

declarch init username/dotfiles/develop

Fetches from explicit branch path.

GitLab

declarch init gitlab.com/username/dotfiles

Direct URL

declarch init https://example.com/config.kdl

Registry module

declarch init hyprland/niri-nico

Typical safe flow

declarch init username/dotfiles --dry-run
declarch init username/dotfiles
declarch lint --mode validate
declarch --dry-run sync

Operational flow

  1. Resolve source candidates.
  2. Download candidate content.
  3. Validate KDL parseability.
  4. Write to local config path.
  5. Initialize missing local structure if needed.

Safety recommendations

# inspect before writing local config
declarch init username/repo --dry-run
  • treat remote config as untrusted input,
  • review hooks and backend commands before full sync,
  • prefer branch/tag pinning for reproducibility.

Failure modes

  • not found: wrong source path/variant/branch.
  • parse error: remote file is not valid KDL.
  • network error: transport or host availability issue.

Troubleshooting flow

declarch -v init username/repo
declarch lint --mode validate

Troubleshooting (Advanced)

Use this page when a command fails or behaves differently than expected. Start with simple checks first, then move to deeper checks.

Quick first checks

declarch lint --mode validate
declarch info --doctor
declarch --dry-run sync

1) Backend not found

Error pattern:

Backend 'xxx' not found

Actions:

declarch init --backend xxx
declarch lint --mode validate

Then confirm backend import in declarch.kdl under backends { ... }. If you are not sure where your config lives on this OS, run:

declarch info --doctor

2) Missing backend binary

Error pattern:

Package manager error: yarn not found

Actions:

  1. install the binary, or
  2. stop using that backend for now, or
  3. set a compatible fallback backend (example: nala -> apt).

Verify with:

declarch info yarn -v

3) Parse errors (KDL)

Error pattern includes line/column.

Actions:

  • fix unbalanced braces
  • check quote usage in strings
  • verify backend command templates include required placeholders ({packages}, {query}, {binary} when needed)

Validate quickly:

declarch lint --mode validate

4) Search timeout/slow backend

Actions:

# narrow scope
declarch search firefox -b flatpak --limit 10

# local-only mode
declarch search firefox --local

If this keeps happening, check backend search/search_local commands and avoid interactive prompts.

5) Sync appears to do nothing

This is often normal: desired state already matches installed state.

Inspect drift/orphans:

declarch info --list --scope orphans

6) Permissions / sudo

If backend requires root, ensure backend is configured correctly (needs_sudo) and your environment can prompt or run privileged commands.

Linux path permission check example:

mkdir -p ~/.config/declarch
chmod 755 ~/.config/declarch

On macOS/Windows, use:

declarch info --doctor

7) State reset procedure

If state is corrupted or stale, reset and re-check:

rm ~/.local/state/declarch/state.json
declarch init
declarch --dry-run sync

For non-Linux paths, first find your real state path with:

declarch info --doctor

8) Debug bundle

Before opening an issue, collect this output:

declarch -v lint --mode validate
declarch -v info --doctor
declarch -v --dry-run sync

Issue tracker:

  • https://github.com/nixval/declarch/issues

Version Pinning (Planned)

Version pinning is not active yet.

Current direction:

  • backend-capability based (not every package manager supports strict pinning)
  • opt-in per package/backend
  • clear handling for unsupported pin requests (warn or error)
  • backward-compatible config/state evolution

When implemented, this page will include:

  • supported backends/capability matrix
  • syntax examples
  • migration notes

Policy, Hooks, and Editor Behavior (Advanced)

This page documents runtime behavior that often impacts safety and automation.

1) Policy block: what it controls

Example:

policy {
    protected "linux" "systemd"
    orphans "ask"
    require_backend "true"
    forbid_hooks "false"
    on_duplicate "warn"
    on_conflict "warn"
}

Meaning (practical):

  • protected: package names that should not be removed by prune-style flows.
  • orphans: orphan handling strategy (keep, remove, ask depending on backend flow).
  • require_backend: force explicit backend declaration; avoid implicit backend behavior.
  • forbid_hooks: hard block hook execution even when CLI uses --hooks.
  • on_duplicate: duplicate declaration policy (warn or error).
  • on_conflict: cross-backend conflict policy (warn or error).

Related checks:

declarch lint --mode validate
declarch lint --mode duplicates
declarch lint --mode conflicts

2) Hooks execution policy (safety gate)

Hooks are intentionally gated by multiple conditions.

Required conditions to execute hooks

  1. Hooks exist in config.
  2. Config explicitly enables hooks:
experimental {
    "enable-hooks"
}
  1. CLI call includes --hooks.
  2. policy.forbid_hooks is not blocking hooks.

If one condition is missing, hooks are skipped/blocked.

Hook phases

Supported lifecycle phases include:

  • pre-sync, post-sync
  • on-success, on-failure
  • pre-install, post-install
  • pre-remove, post-remove
  • on-update

Hook command safety rules

Hook command validation rejects risky patterns, including:

  • embedded sudo in command string
  • path traversal patterns like ../
  • unsafe characters outside allowed safe set

Runtime details:

  • hook timeout is enforced
  • behavior on failure depends on hook error policy (warn, required, ignore)

3) Editor selection policy (declarch edit)

Current runtime priority (actual behavior):

  1. editor value from root config (declarch.kdl)
  2. $VISUAL
  3. $EDITOR
  4. fallback to nano

If configured editor is missing in PATH, declarch warns and falls through to next option.

Useful edit flags:

declarch edit mymodule --preview --number
declarch edit mymodule --validate-only
declarch edit mymodule --auto-format
declarch edit mymodule --backup

4) Self-update ownership policy

self-update is intentionally constrained by install ownership.

If installation is owned by an external package manager (AUR/Homebrew/Scoop/Winget), declarch does not force direct overwrite and instead shows update hints for that package manager.

Use package-manager-native update command in those cases.

declarch lint --mode validate
declarch lint --mode duplicates
declarch lint --mode conflicts
declarch --dry-run sync --hooks
declarch sync --hooks

If hooks are not expected to run, verify:

  • experimental { "enable-hooks" }
  • --hooks is present
  • policy.forbid_hooks is not enabled

Integration Examples (API, MCP, Plugins)

This page shows practical integration patterns you can build around declarch. Core idea: keep declarch simple, extend behavior from outside.

Extension examples (external executables)

1) Security audit plugin

Command name example: declarch-ext-security-audit

  • Reads package inventory from:
    • declarch info --list --format json --output-version v1
  • Checks vulnerability/advisory sources.
  • Outputs risk summary for CI.

2) Notification plugin

Command name example: declarch-ext-notify

  • Runs after sync in CI/local automation.
  • Sends concise report to Discord/Slack/Telegram.
  • Useful for shared infra/team setups.

3) Team policy plugin

Command name example: declarch-ext-policy-team

  • Rejects forbidden packages/backends before apply.
  • Enforces naming/module conventions.
  • Great for organization-wide baseline rules.

4) Export plugin

Command name example: declarch-ext-export

  • Converts declarch managed state/plan into other formats:
    • CSV/JSON inventory
  • infra report artifacts
  • dashboard feed input

Protocol reference:

  • docs/contracts/v1/extensions-protocol.md

MCP examples (good first step)

Read-only MCP tools are low-risk and high value.

Candidate MCP tools:

  • declarch_info
  • declarch_lint
  • declarch_search
  • declarch_sync_dry_run

These can call declarch and parse machine output (v1 envelope).

API examples (optional)

If needed later, an API can mirror existing command surfaces:

  • GET /info
  • GET /lint
  • GET /search?q=...
  • POST /sync/dry-run

Keep API responses aligned with the same v1 envelope contract.

Integrations in CI/CD

  • PR validation:
    • declarch lint --strict
    • declarch --dry-run sync
  • Artifact export:
    • store info/list machine output as CI artifacts.
  • Team notifications:
    • send drift warnings or preview summaries.

Suggested rollout order

  1. Stabilize machine output contracts (v1).
  2. Build read-only MCP adapter externally.
  3. Add extension discovery/runtime (declarch ext) incrementally.
  4. Re-evaluate embedded API only when real usage needs it.

MCP Setup (Technical)

This page shows how to connect declarch with MCP clients while keeping core behavior agnostic and safe.

Scope

  • MCP adapter is external (declarch-mcp), not in-process plugin code.
  • Core declarch logic is unchanged.
  • Read-only tools are available by default.
  • Write/apply action is blocked by default and requires explicit opt-in.
  • declarch-mcp is a local stdio adapter.
  • declarch does not ship a built-in public HTTP MCP server in this guide.

Important: MCP config format is client-specific

MCP protocol standardizes message transport (JSON-RPC over stdio/http), not one universal mcpServers file schema for every app.

So:

  • command + args + env pattern is common.
  • exact file path and key names depend on each client.
  • your client config may look different and still be valid.

Why some examples are only command

For local stdio MCP, many clients can start a server process with just:

  • command: executable name/path

So this is valid when declarch-mcp is already in PATH:

{
  "mcpServers": {
    "declarch": {
      "command": "declarch-mcp"
    }
  }
}

Add other fields only when needed:

  • args: if your server needs startup arguments
  • env: if you need custom environment variables
  • type, url, headers: for remote HTTP/SSE servers

Important:

  • If you only use local stdio, command (and optional args/env) is enough.
  • url/headers are only for clients that connect to remote HTTP MCP servers.

Safety model (default read-only)

By default, MCP write actions are disabled.

To allow a write tool, enable it explicitly in declarch.kdl:

mcp {
    mode "write-enabled"
    allow_tools "declarch_sync_apply"
}

Without this block, write calls are rejected even if client sends them.

Common fields across clients (quick map)

  • Local stdio (process on your machine):
    • usually command
    • optional args, env
    • some clients also accept/require type: "stdio" or type: "local"
  • Remote MCP over network:
    • usually url (or httpUrl / serverUrl depending client)
    • optional/required type (http, streamableHttp, sse)
    • optional headers for auth

Start from normal declarch setup:

declarch init

Linux defaults are usually:

  • config: ~/.config/declarch
  • state: ~/.local/state/declarch

Use this to confirm your actual paths:

declarch info --doctor

Binary requirement

Your MCP client must be able to run declarch-mcp.

  • If installed in PATH: use command = "declarch-mcp" (or JSON equivalent).
  • If not in PATH: set command to the full binary path.

DECLARCH_BIN is optional and only needed when you want to force a specific declarch binary.

Tools exposed

  • declarch_info
  • declarch_list
  • declarch_lint
  • declarch_search
  • declarch_sync_dry_run
  • declarch_sync_apply (only listed when config allows it)

Quick copy: generic local MCP config

Use this template and adapt keys to your client schema:

{
  "mcpServers": {
    "declarch": {
      "command": "declarch-mcp"
    }
  }
}

That is enough for standard usage. declarch will use normal OS default paths automatically.

If declarch-mcp is not in PATH yet, set command to the full binary path.

Quick copy: Codex (~/.codex/config.toml)

[mcp_servers.declarch]
command = "declarch-mcp"
args = []

Optional only if you want to force a specific declarch binary:

[mcp_servers.declarch.env]
DECLARCH_BIN = "/path/to/declarch"

Optional guarded apply:

[mcp_servers.declarch.env]
DECLARCH_MCP_ALLOW_APPLY = "1"

Quick copy: Gemini (~/.gemini/antigravity/mcp_config.json)

{
  "mcpServers": {
    "declarch": {
      "command": "declarch-mcp",
      "args": []
    }
  }
}

Optional:

{
  "mcpServers": {
    "declarch": {
      "command": "declarch-mcp",
      "env": {
        "DECLARCH_BIN": "/path/to/declarch"
      }
    }
  }
}

Quick copy: Qwen (~/.qwen/settings.json)

Some Qwen setups accept command + args directly. If env fields are not supported in your version, use a shell wrapper:

{
  "mcpServers": {
    "declarch": {
      "command": "bash",
      "args": [
        "-lc",
        "declarch-mcp"
      ]
    }
  }
}

Enable guarded apply in Qwen wrapper command by adding:

DECLARCH_MCP_ALLOW_APPLY=1

inside the same bash -lc command string.

Quick copy: Claude Code

Claude setup can vary by app version and integration mode. If your config file does not expose a direct mcpServers block, use Claude's MCP config location for your version and map the same payload below.

Use your Claude MCP server config location/schema, then map it to the same payload:

  • command: .../declarch-mcp
  • optional env: DECLARCH_BIN (only when needed)
  • optional env: DECLARCH_MCP_ALLOW_APPLY=1 (only when you want write/apply)

Quick copy: enable guarded apply

If you explicitly want AI to run declarch sync apply:

{
  "mcpServers": {
    "declarch": {
      "command": "declarch-mcp",
      "env": {
        "DECLARCH_MCP_ALLOW_APPLY": "1"
      }
    }
  }
}

Also add config consent in declarch.kdl:

mcp {
    mode "write-enabled"
    allow_tools "declarch_sync_apply"
}

And MCP call must include:

{
  "name": "declarch_sync_apply",
  "arguments": {
    "confirm": "APPLY_SYNC"
  }
}

Without config consent + env guard + confirm token, apply is rejected.

Client notes

  • Different clients use different config file paths/field names.
  • Keep the same command/env payload, then adapt to each client’s schema.
  • Start with read-only tools first, then enable apply only when needed.
  • Do not commit real API keys/tokens from client config files.
  • When a client supports both local and remote MCP, start with local stdio first.

Optional: custom XDG (advanced)

Custom XDG is optional and usually only needed for isolated test setups.

Cross-Distro Support

Declarch is distro-agnostic. Real behavior depends on which backend binaries and backend configs are available.

How to think about it

  • Declarch = coordinator.
  • Backends = actual package-manager commands.
  • You can mix distro/system + language backends in one file.

Common backend groups

  • Arch-oriented: aur, pacman
  • Debian/Ubuntu: apt, nala
  • Fedora/RHEL: dnf
  • Universal: flatpak, snap, nix, soar
  • Language/dev: npm, pnpm, yarn, bun, cargo, pip, gem, go

Starter commands

Arch-based

declarch init
declarch init --backend paru,yay

Debian/Ubuntu

declarch init
declarch init --backend apt,nala,npm,cargo

Fedora

declarch init
declarch init --backend dnf,flatpak,npm,cargo

Fallback examples

  • nala -> apt
  • yay -> pacman
  • bun -> npm
  • aur -> paru -> yay -> pacman

Fallback keeps workflows usable when preferred binary is missing.

Improve support

Contribute backend definitions and fixes:

  • https://github.com/nixval/declarch-packages