Metadata-Version: 2.5
Name: axm-config
Version: 0.1.0
Summary: Non-sensitive runtime config under ~/.axm (env>file>default)
Project-URL: Homepage, https://github.com/axm-protocols/axm-forge-workspace
Project-URL: Documentation, https://axm-protocols.github.io/axm-forge-workspace/
Project-URL: Repository, https://github.com/axm-protocols/axm-forge-workspace.git
Project-URL: Issues, https://github.com/axm-protocols/axm-forge-workspace/issues
Author-email: Gabriel Jarry <jarry.gabriel@gmail.com>
License-Expression: Apache-2.0
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.12
Requires-Dist: axm
Requires-Dist: cyclopts>=4.21.0
Requires-Dist: pydantic>=2.13.4
Requires-Dist: tomli-w>=1.2.0
Description-Content-Type: text/markdown

# axm-config

Non-sensitive runtime config under ~/.axm (env>file>default)

<p align="center">
  <a href="https://github.com/axm-protocols/axm-forge/actions/workflows/ci.yml"><img src="https://github.com/axm-protocols/axm-forge/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
  <a href="https://forge.axm-protocols.io/audit/"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/axm-protocols/axm-forge/gh-pages/badges/axm-config/axm-audit.json" alt="axm-audit"></a>
  <a href="https://forge.axm-protocols.io/init/"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/axm-protocols/axm-forge/gh-pages/badges/axm-config/axm-init.json" alt="axm-init"></a>
  <a href="https://github.com/axm-protocols/axm-forge/actions/workflows/axm-quality.yml"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/axm-protocols/axm-forge/gh-pages/badges/axm-config/coverage.json" alt="Coverage"></a>
  <img src="https://img.shields.io/badge/python-3.12%2B-blue" alt="Python 3.12+">
</p>

---

## Overview

Non-sensitive runtime config under ~/.axm (env>file>default)

## Features

- 🏠 **`~/.axm` home** — `axm_home()` resolves and creates the per-user config
  directory `0700` (idempotent, tightens looser perms)
- 🧪 **Isolated profiles** — `AXM_PROFILE=dev` routes reads, writes, deletes,
  model loading, legacy files, and enumeration to
  `~/.axm/profiles/dev/config.toml`. A missing profile store falls through to
  defaults, never production; the directory is created on first write
- 🧭 **Layered resolution** — `get` / `set_` / `delete` resolve a
  `(namespace, key)` with `env > file > default` precedence; the env name is
  derived deterministically as `AXM_<NS>_<KEY>` (upper-cased, each namespace dot
  → a *double* underscore). The mapping is provably injective and POSIX-valid
- ⚙️ **Typed execution policies** — per-ticket-type backend/model and analysis
  overrides use the same atomic store. For `dev.work`, the environment keys are
  exactly `AXM_EXECUTION__DEV__WORK_BACKEND`,
  `AXM_EXECUTION__DEV__WORK_MODEL`, and
  `AXM_EXECUTION__DEV__WORK_ANALYSIS_ENABLED`
- 🗄️ **Single-file store per profile** — production uses the atomic
  `~/.axm/config.toml` (`0600`); named profiles use
  `~/.axm/profiles/<name>/config.toml`. Each has a `[namespace]` table per
  namespace; a read-modify-write preserves every other section, an
  absent/corrupt file degrades to `{}`, and profile-local legacy files are
  folded in on the next write
- 🛡️ **Path-traversal safe** — `namespace`/`key` are validated at every public
  boundary (lowercase-only patterns; traversal/empty/NUL raise `ConfigError`),
  and a `HOME` resolving inside a git checkout is refused as `UnsafeHomeError`
- 🧬 **Model binding** — `load(namespace, model)` populates a pydantic model,
  resolving each field by name; a missing required field raises `ConfigError`
- 🩺 **Provenance doctor** — the `config_doctor` AXMTool reports which layer
  (`env` / `file` / `default`) wins per visible key, read-only; over MCP, the
  `axm` CLI, and `axm-config doctor`
- 🖥️ **`axm-config` CLI** — `get` / `set` / `delete` / `path` / `doctor`
  wrap the same central resolution layer for shell use

## Installation

```bash
uv add axm-config
```

Or as a workspace dependency in `pyproject.toml`:

```toml
[project]
dependencies = ["axm-config"]

[tool.uv.sources]
axm-config = { workspace = true }
```

## Development

This package is part of the [**axm-forge**](https://github.com/axm-protocols/axm-forge) workspace.

```bash
git clone https://github.com/axm-protocols/axm-forge.git
cd axm-forge
uv sync --all-groups
uv run --package axm-config --directory packages/axm-config pytest -x -q
```

## License

Apache-2.0 — © 2026 Gabriel Jarry
