Metadata-Version: 2.4
Name: agh
Version: 0.7.0
Summary: Self-hosted guidance distribution for coding agents
License-Expression: MIT
Project-URL: Homepage, https://github.com/giulianotesta7/AgentGuidanceHub
Project-URL: Documentation, https://github.com/giulianotesta7/AgentGuidanceHub#readme
Project-URL: Source, https://github.com/giulianotesta7/AgentGuidanceHub
Project-URL: Issues, https://github.com/giulianotesta7/AgentGuidanceHub/issues
Project-URL: Releases, https://github.com/giulianotesta7/AgentGuidanceHub/releases
Project-URL: Container, https://github.com/giulianotesta7/AgentGuidanceHub/pkgs/container/agent-guidance-hub
Keywords: agent-tools,ai-agents,cli,coding-agents,developer-tools,fastapi,self-hosted
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Framework :: FastAPI
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development
Classifier: Topic :: Software Development :: Build Tools
Classifier: Topic :: System :: Systems Administration
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: fastapi>=0.110
Requires-Dist: typer>=0.12
Requires-Dist: uvicorn[standard]>=0.27
Dynamic: license-file

<div align="center">

# Agent Guidance Hub (AGH)

<p><strong>Self-hosted guidance distribution for coding agents.</strong></p>

<p>
  <a href="https://pypi.org/project/agh/"><img alt="PyPI" src="https://img.shields.io/pypi/v/agh?color=1f6feb"></a>
  <a href="https://github.com/giulianotesta7/AgentGuidanceHub/pkgs/container/agent-guidance-hub"><img alt="GHCR" src="https://img.shields.io/badge/ghcr-agent--guidance--hub-1f6feb"></a>
  <a href="https://github.com/giulianotesta7/AgentGuidanceHub/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/giulianotesta7/AgentGuidanceHub/actions/workflows/ci.yml/badge.svg"></a>
  <a href="https://github.com/giulianotesta7/AgentGuidanceHub/releases"><img alt="Release" src="https://img.shields.io/github/v/release/giulianotesta7/AgentGuidanceHub"></a>
</p>

<p>
  <a href="#install">install</a> · <a href="#quick-start">quick start</a> · <a href="#how-agh-works">how it works</a> · <a href="#server-operations">server ops</a> · <a href="#development">development</a> · <a href="README.es.md">español</a>
</p>

</div>

[Español](README.es.md)

---

![AGH workspace pull demo](assets/agh-workspace-demo.gif)

**AGH gives teams one place to publish, version, assign, and pull reusable agent instructions and skills into their repos.**

Use it when agent guidance needs the same discipline as infrastructure: reproducible changes, clear ownership, and self-hosted runtime. AGH is early, Docker-first, and published as a PyPI package, Homebrew formula, and GHCR server image.

- **Centralize guidance**: publish shared `AGENTS.md`, `CLAUDE.md`, and skill files once.
- **Version every change**: packages are immutable SemVer releases assigned to projects.
- **Keep repos deterministic**: each workspace records `.agh/lock.toml` and applies only the selected target.
- **Run it yourself**: host the server with Docker, SQLite, and persistent `/data` storage.

---

## Install

Linux / macOS:

```bash
brew install giulianotesta7/tap/agh
```

Windows (Scoop):

```powershell
scoop bucket add agh https://github.com/giulianotesta7/scoop-agh
scoop install agh
```

or install with script:

```bash
curl -fsSL https://raw.githubusercontent.com/giulianotesta7/AgentGuidanceHub/main/scripts/install.sh | sh
```

or install with uv:

```bash
uv tool install --force agh
```

from a checkout:

```bash
git clone https://github.com/giulianotesta7/AgentGuidanceHub.git
cd AgentGuidanceHub
uv tool install --force .
```

check the CLI:

```bash
agh --help
```

Run the server with the published Docker image:

```bash
docker compose up -d
curl http://127.0.0.1:8912/api/v1/health
```

The default Compose image is:

```text
ghcr.io/giulianotesta7/agent-guidance-hub:${AGH_IMAGE_TAG:-latest}
```

Pin production deployments with a release tag:

```bash
AGH_IMAGE_TAG=0.2.0 docker compose up -d
```

## Quick start

Read the first owner token on the host running AGH:

```bash
docker run --rm -v agh-data:/data busybox \
  cat /data/secrets/initial_owner_token
```

Configure the instance URL once, then log in from your machine:

```bash
agh config set <instance-url>
agh login --email owner@example.com --token "<initial-owner-token>"
```

`agh config` shows the configured instance URL:

```bash
agh config
```

Use `agh config clear` to remove the instance URL, and `agh logout` to clear stored credentials without changing the instance.

Create a project with the repo URL developers use in git remotes:

```bash
agh project create "Agent Guidance Hub" \
  --git-url https://github.com/giulianotesta7/AgentGuidanceHub.git
```

Work from a linked repo:

```bash
agh link
agh target set opencode # or: agh target set claude
agh pull --dry-run
agh pull
agh target
```

`agh target` shows the selected target for this workspace; use `agh target clear` to remove the workspace selection or add `--global` to manage the global default.

## How AGH works

```text
Package author ── publish ──▶ AGH server ── assign ──▶ Project
                              │                         │
                              │                         ▼
                         SQLite + /data          Repo workspace
                                                       │
                                                       ├─ AGENTS.md + .opencode/skills/
                                                       └─ CLAUDE.md + .claude/skills/
```

| Piece | What it does |
|-------|--------------|
| Packages | Shared instructions, skills, or both. Published versions are immutable. |
| Projects | One git repository plus the package versions it should use. |
| Workspaces | A local repo linked with `agh link`, one selected target, and a committed lockfile. |

<details>
<summary><strong>Package authoring</strong></summary>

A package starts with this shape:

```text
my-package/
├── agh.package.toml
├── instructions/
│   ├── AGENTS.md
│   └── CLAUDE.md
└── skills/
    └── reviewer/
        └── SKILL.md
```

Create a template:

```bash
agh package init ./my-package --domain acme --name onboarding --version 1.0.0
```

The manifest starts as:

```toml
domain = "acme"
name = "onboarding"
version = "1.0.0"
description = "TODO"
```

Useful starter flags:

- `--with-agents` creates `instructions/AGENTS.md`.
- `--with-claude` creates `instructions/CLAUDE.md`.
- `--with-skill NAME` creates `skills/NAME/SKILL.md`.

Allowed files:

- `agh.package.toml`
- `instructions/AGENTS.md`
- `instructions/CLAUDE.md`
- `skills/<name>/SKILL.md`

Rules:

- A package can contain instructions, skills, or both.
- It must include at least one instruction file or skill.
- `version` must be exact SemVer, such as `1.0.0`.
- Published versions are immutable. Publish `1.0.1` for changes.
- Do not publish `latest`. Use `latest` only when assigning packages to projects.
- Use UTF-8 text files. Do not include symlinks.

Publish and list packages:

```bash
agh package publish ./my-package
agh package list
```

Example publish output:

```text
Published acme/onboarding@1.0.0.
Package ID: pkg_...
Checksum: sha256:...
```

</details>

<details>
<summary><strong>Project assignment</strong></summary>

A project is an AGH record linked to one git repository.

```bash
agh project create "Agent Guidance Hub" \
  --git-url https://github.com/giulianotesta7/AgentGuidanceHub.git
agh project list
agh project describe prj_...
agh project update prj_... --name "App API"
agh project deactivate prj_...
agh project member list prj_...
```

Project commands that take a project reference accept `prj_...` ids or exact project names. All-digit values are treated as ids, and project names cannot contain only digits.

Assign packages through the unified `package` commands with exactly one target scope (`--project` or `--collection`):

```bash
agh package assign acme/onboarding@latest --project prj_...
agh package list --project prj_...
agh package describe acme/onboarding@1.0.0
agh package activate acme/onboarding@latest --project prj_...
agh package deactivate acme/onboarding@latest --project prj_...
agh package unassign acme/onboarding@latest --project prj_...
```

Package inputs accept `pkgv_...`, `domain/name@version`, and exact `name@version` refs. No-domain refs must match a single package domain, otherwise AGH reports a conflict. Use an exact version to pin the project. Use `latest` with domain-qualified refs when the project should resolve to the newest published version during pull. `package describe PACKAGE_REF@latest` resolves to the highest SemVer version.

The server keeps assignment ids internal: activate, deactivate, and unassign look up the existing assignment by package ref plus target scope. When a package is not assigned, the failure names the package ref, scope, and scope id and suggests `agh package list --<scope> <id>`.

During workspace pull, AGH writes the resolved concrete version and checksum to `.agh/lock.toml`.

</details>

<details>
<summary><strong>Collection administration</strong></summary>

Collections group skill-only packages that members install through `agh skill ...`. Owners and admins manage collections with the `agh collection` commands. These admin commands are separate from the consumer `agh skill ...` flow.

```bash
agh collection create "Team Skills" --description "Shared review skills"
agh collection list
agh collection describe "Team Skills"
agh collection update "Team Skills" --name "Review Skills"
agh collection deactivate "Review Skills"
```

Collection commands that take a collection reference accept `col_...` ids or exact active collection names. Canonical ids skip name resolution; exact names resolve through the active-collection by-name endpoint.

Assign skill-only packages to a collection through the unified `package` commands with `--collection`:

```bash
agh package assign acme/reviewer@latest --collection "Team Skills"
agh package list --collection "Team Skills"
agh package activate acme/reviewer@latest --collection "Team Skills"
agh package deactivate acme/reviewer@latest --collection "Team Skills"
agh package unassign acme/reviewer@latest --collection "Team Skills"
```

Collection packages must be skill-only: AGH rejects packages that contain `instructions/AGENTS.md`, `instructions/CLAUDE.md`, or no skills, and the CLI surfaces that server validation. Package inputs accept `pkgv_...`, `domain/name@version`, and exact `name@version` refs. Assignment requires both the collection and the package reference; there is no interactive picker, since only the server can validate skill-only packages.

</details>

<details>
<summary><strong>Global skills</strong></summary>

Global skills are collection-backed tools installed into the selected target's native user-level skill directory. A collection is an AGH-managed group of skill-only packages made available by the server; global skills are separate from workspace package assignments.

| Command | What it does |
|---------|--------------|
| `agh skill list` | Lists skills available from active collections. |
| `agh skill install acme/commenting@latest reviewer --target opencode` | Resolves, downloads, and installs `reviewer` globally for the `opencode` target. |

Target resolution for `skill install` follows this order: an explicit `--target`, the workspace target (`.agh-cache/preferences.toml`), the global target, then an interactive prompt. In non-interactive mode AGH exits with code `2` instead of prompting.

If no target is saved and `--target` is omitted, AGH prompts with:

```text
Select the target for global skills:
```

Install paths:

- OpenCode global skills: `~/.config/opencode/skills`
- Claude global skills: `~/.claude/skills`

Global skill state is local user state under `XDG_STATE_HOME/agh` or `~/.local/state/agh`; it does not change workspace pull behavior or `.agh/lock.toml`.

</details>

<details>
<summary><strong>Workspace pull and Git state</strong></summary>

| Command | What it does |
|---------|--------------|
| `agh link` | Matches the git remote to an AGH project and writes `.agh/project.toml`. |
| `agh target` | Shows the current local target selection. |
| `agh target set opencode` | Selects OpenCode for this workspace. |
| `agh target set claude` | Selects Claude Code for this workspace. |
| `agh target clear` | Removes the local workspace target selection. |
| `agh pull --dry-run` | Fetches the server plan without writing repo files. |
| `agh pull` | Applies instructions and skills for the selected target and writes `.agh/lock.toml`. |
| `agh pull --force` | Replaces conflicted AGH blocks or skill targets. |

There is no `both` option. If no target is selected, interactive `agh pull` asks which target to use. Skip exits with code `2` and writes nothing.

Instruction files use managed blocks:

```md
<!-- AGH-BEGIN package="<package-ref>" artifact="instructions/AGENTS.md" checksum="sha256:..." -->
Project instructions from AGH live here.
<!-- AGH-END package="<package-ref>" -->
```

If you edit inside the block, the next `agh pull` exits with conflict code `3`. Use `agh pull --force` when AGH should replace it.

Skills go where agents already look:

```text
.claude/skills/<skill>/SKILL.md
.opencode/skills/<skill>/SKILL.md
```

AGH tries a relative symlink to `.agh-cache/packages/...`. If the OS rejects symlinks, AGH copies the file. The lockfile records the mode:

```toml
[[packages]]
package_ref = "acme/onboarding@1.0.0"

[[artifacts]]
package_ref = "acme/onboarding@1.0.0"
path = "skills/reviewer/SKILL.md"
target_path = ".opencode/skills/reviewer/SKILL.md"
mode = "symlink" # or mode = "copy"
source = ".agh-cache/packages/acme/onboarding/1.0.0/skills/reviewer/SKILL.md"
```

Commit shared workspace state:

- `.agh/project.toml`
- `.agh/lock.toml`
- generated `AGENTS.md` / `CLAUDE.md` when your team wants those reviewed
- generated `.claude/skills/` or `.opencode/skills/` when your team wants skills reviewed

Do not commit local cache state:

```gitignore
.agh-cache/
```

AGH downloads packages to `.agh-cache/packages/` and stores each developer's target choice in `.agh-cache/preferences.toml`. If skill targets are symlinks, a fresh clone needs `agh pull` to rebuild the cache before those links resolve.

Exit codes:

| Code | Meaning |
|------|---------|
| `0` | Success or no changes. |
| `1` | Runtime/API/download failure. |
| `2` | Local validation, malformed manifest, or missing/skipped target selection. |
| `3` | Conflict. |
| `4` | Authentication/authorization failure. |
| `5` | Workspace is not linked; run `agh link`. |

</details>

## Server operations

The first owner token is written once:

```text
/data/secrets/initial_owner_token
```

Store it. AGH will not show it again. The server stores token hashes, not plaintext tokens.

| Role | Use |
|------|-----|
| `owner` | Full admin access, including bootstrap ownership. |
| `admin` | Manage users, projects, packages, and assignments. |
| `member` | Day-to-day workspace access. |

Admin commands:

```bash
agh user list
agh user create user@example.com --role admin
agh user describe user@example.com
agh user update usr_... --role member
agh user activate usr_...
agh user deactivate usr_...
agh user token rotate usr_...
agh whoami
agh logout
agh config
agh config clear
```

User commands that take a user reference accept `usr_...` ids or exact emails. Token rotation is nested under `user`: `agh user token rotate USER_REF`.

The CLI stores login credentials locally for authentication; `agh config` shows only the instance URL, never the token.

Runtime state lives under `/data`:

| Path | Purpose |
|------|---------|
| `/data/agh.sqlite3` | SQLite database. |
| `/data/packages/` | Published package payloads. |
| `/data/logs/agh.log` | Server log. |
| `/data/secrets/initial_owner_token` | First owner token, created once. |

The image owns `/data` as `agh:agh` (`10001:10001`) at build time.
Named Docker volumes are initialized from that image-owned `/data` tree.
Bind mounts must already be writable by UID/GID `10001:10001`; the container does not repair host ownership.

Direct Docker run:

```bash
docker run --rm -p 8912:8912 -v agh-data:/data \
  -e AGH_BOOTSTRAP_OWNER_EMAIL=owner@example.com \
  ghcr.io/giulianotesta7/agent-guidance-hub:0.2.0
```

Healthcheck:

```bash
curl http://127.0.0.1:8912/api/v1/health
```

Backup at least:

```text
/data/agh.sqlite3
/data/packages/
/data/secrets/
```

Upgrade by pinning the next image tag and restarting:

```bash
AGH_IMAGE_TAG=0.2.0 docker compose pull
AGH_IMAGE_TAG=0.2.0 docker compose up -d
```

## Development

```bash
uv sync
uv run pytest
uv run uvicorn agh.server.app:app --host 0.0.0.0 --port 8912
```

Local data uses `.agh-data/` by default.

Contributing and security:

- [Contributing](CONTRIBUTING.md)
- [Security](SECURITY.md)

### Third-party notices

AGH includes project-specific skills adapted from third-party skill workflows.

- `skills/agh-branch-pr` is adapted from `skills/branch-pr/SKILL.md` in
  [`Gentleman-Programming/gentle-ai`](https://github.com/Gentleman-Programming/gentle-ai),
  licensed under Apache-2.0, and modified for AGH's PR-first contribution policy.
- `skills/agh-issue-flow` is adapted from `skills/issue-creation/SKILL.md` in
  [`Gentleman-Programming/gentle-ai`](https://github.com/Gentleman-Programming/gentle-ai),
  licensed under Apache-2.0, and modified for AGH's PR-first contribution policy
  and minimal issue-label workflow.
- `skills/agh-work-unit-commits` is adapted from `skills/work-unit-commits/SKILL.md`
  in [`Gentleman-Programming/gentle-ai`](https://github.com/Gentleman-Programming/gentle-ai),
  licensed under Apache-2.0, and modified for AGH's Python/uv validation workflow,
  docs mirror policy, and PR-first contribution model.
- `skills/agh-chained-pr` is adapted from `skills/chained-pr/SKILL.md` and
  `skills/chained-pr/references/chaining-details.md` in
  [`Gentleman-Programming/gentle-ai`](https://github.com/Gentleman-Programming/gentle-ai),
  licensed under Apache-2.0, and modified for AGH's PR-first contribution policy,
  minimal labels, Python/uv validation, and single-maintainer review flow.
- `skills/agh-docs-alignment` is adapted from `skills/docs-alignment/SKILL.md` in
  [`Gentleman-Programming/engram`](https://github.com/Gentleman-Programming/engram/tree/main/skills/docs-alignment),
  licensed under Apache-2.0, and modified for AGH's README-as-guide model,
  bilingual mirror policy, docs-test validation, and PR-first contribution flow.
- `skills/agh-testing-coverage` is adapted from `skills/testing-coverage/SKILL.md`
  in [`Gentleman-Programming/engram`](https://github.com/Gentleman-Programming/engram/tree/main/skills/testing-coverage),
  licensed under Apache-2.0, and modified for AGH's Python/uv, FastAPI/Typer,
  Docker, docs-guidance, and package-validation workflow.
