Agent Guidance Hub (AGH)
Self-hosted guidance distribution for coding agents.
install · quick start · how it works · server ops · development · español
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.tomland applies only the selected target. - Run it yourself: host the server with Docker, SQLite, and persistent
/datastorage.
Install
Linux / macOS:
brew install giulianotesta7/tap/agh
Windows (Scoop):
scoop bucket add agh https://github.com/giulianotesta7/scoop-agh
scoop install agh
or install with script:
curl -fsSL https://raw.githubusercontent.com/giulianotesta7/AgentGuidanceHub/main/scripts/install.sh | sh
or install with uv:
uv tool install --force agh
from a checkout:
git clone https://github.com/giulianotesta7/AgentGuidanceHub.git
cd AgentGuidanceHub
uv tool install --force .
check the CLI:
agh --help
Run the server with the published Docker image:
docker compose up -d
curl http://127.0.0.1:8912/api/v1/health
The default Compose image is:
ghcr.io/giulianotesta7/agent-guidance-hub:${AGH_IMAGE_TAG:-latest}
Pin production deployments with a release tag:
AGH_IMAGE_TAG=0.2.0 docker compose up -d
Quick start
Read the first owner token on the host running AGH:
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:
agh config set <instance-url>
agh login --email owner@example.com --token "<initial-owner-token>"
agh config shows the configured instance URL:
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:
agh project create "Agent Guidance Hub" \
--git-url https://github.com/giulianotesta7/AgentGuidanceHub.git
Work from a linked repo:
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
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. |
Package authoring
A package starts with this shape:
my-package/
├── agh.package.toml
├── instructions/
│ ├── AGENTS.md
│ └── CLAUDE.md
└── skills/
└── reviewer/
└── SKILL.md
Create a template:
agh package init ./my-package --domain acme --name onboarding --version 1.0.0
The manifest starts as:
domain = "acme"
name = "onboarding"
version = "1.0.0"
description = "TODO"
Useful starter flags:
--with-agentscreatesinstructions/AGENTS.md.--with-claudecreatesinstructions/CLAUDE.md.--with-skill NAMEcreatesskills/NAME/SKILL.md.
Allowed files:
agh.package.tomlinstructions/AGENTS.mdinstructions/CLAUDE.mdskills/<name>/SKILL.md
Rules:
- A package can contain instructions, skills, or both.
- It must include at least one instruction file or skill.
versionmust be exact SemVer, such as1.0.0.- Published versions are immutable. Publish
1.0.1for changes. - Do not publish
latest. Uselatestonly when assigning packages to projects. - Use UTF-8 text files. Do not include symlinks.
Publish and list packages:
agh package publish ./my-package
agh package list
Example publish output:
Published acme/onboarding@1.0.0.
Package ID: pkg_...
Checksum: sha256:...
Project assignment
A project is an AGH record linked to one git repository.
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):
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.
Collection administration
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.
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:
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.
Global skills
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:
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.
Workspace pull and Git state
| 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:
<!-- 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:
.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:
[[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.mdwhen your team wants those reviewed - generated
.claude/skills/or.opencode/skills/when your team wants skills reviewed
Do not commit local cache state:
.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. |
Server operations
The first owner token is written once:
/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:
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:
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:
curl http://127.0.0.1:8912/api/v1/health
Backup at least:
/data/agh.sqlite3
/data/packages/
/data/secrets/
Upgrade by pinning the next image tag and restarting:
AGH_IMAGE_TAG=0.2.0 docker compose pull
AGH_IMAGE_TAG=0.2.0 docker compose up -d
Development
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:
Third-party notices
AGH includes project-specific skills adapted from third-party skill workflows.
skills/agh-branch-pris adapted fromskills/branch-pr/SKILL.mdinGentleman-Programming/gentle-ai, licensed under Apache-2.0, and modified for AGH's PR-first contribution policy.skills/agh-issue-flowis adapted fromskills/issue-creation/SKILL.mdinGentleman-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-commitsis adapted fromskills/work-unit-commits/SKILL.mdinGentleman-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-pris adapted fromskills/chained-pr/SKILL.mdandskills/chained-pr/references/chaining-details.mdinGentleman-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-alignmentis adapted fromskills/docs-alignment/SKILL.mdinGentleman-Programming/engram, 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-coverageis adapted fromskills/testing-coverage/SKILL.mdinGentleman-Programming/engram, licensed under Apache-2.0, and modified for AGH's Python/uv, FastAPI/Typer, Docker, docs-guidance, and package-validation workflow.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file agh-0.7.0.tar.gz.
File metadata
- Download URL: agh-0.7.0.tar.gz
- Upload date:
- Size: 412.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
794bcfa20dd408eff9f288f5c93e9f9f9c591afb284d18092f8a894285b470f7
|
|
| MD5 |
164f9f63b8892585d4bdb623e9d04739
|
|
| BLAKE2b-256 |
b4d9d96993f921e187687ea07f67e6f591031a8921cf73ebe1dbdc9e19238ca5
|
Provenance
The following attestation bundles were made for agh-0.7.0.tar.gz:
Publisher:
release.yml on giulianotesta7/AgentGuidanceHub
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agh-0.7.0.tar.gz -
Subject digest:
794bcfa20dd408eff9f288f5c93e9f9f9c591afb284d18092f8a894285b470f7 - Sigstore transparency entry: 2123523856
- Sigstore integration time:
-
Permalink:
giulianotesta7/AgentGuidanceHub@246e7528bc3833b7893d9529fce1c9dbe9f0d06c -
Branch / Tag:
refs/tags/v0.7.0 - Owner: https://github.com/giulianotesta7
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@246e7528bc3833b7893d9529fce1c9dbe9f0d06c -
Trigger Event:
push
-
Statement type:
File details
Details for the file agh-0.7.0-py3-none-any.whl.
File metadata
- Download URL: agh-0.7.0-py3-none-any.whl
- Upload date:
- Size: 97.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6551ea40279fec7e2d8e91ec710fc4280ff623f4430b14aa86520944134a5680
|
|
| MD5 |
830235add11d94a9e708703d45d8c1a0
|
|
| BLAKE2b-256 |
d7bf524b13785bb96d310ada2dbf3f319d30cd671bb7d432b64ffb9a5e6d250a
|
Provenance
The following attestation bundles were made for agh-0.7.0-py3-none-any.whl:
Publisher:
release.yml on giulianotesta7/AgentGuidanceHub
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agh-0.7.0-py3-none-any.whl -
Subject digest:
6551ea40279fec7e2d8e91ec710fc4280ff623f4430b14aa86520944134a5680 - Sigstore transparency entry: 2123523891
- Sigstore integration time:
-
Permalink:
giulianotesta7/AgentGuidanceHub@246e7528bc3833b7893d9529fce1c9dbe9f0d06c -
Branch / Tag:
refs/tags/v0.7.0 - Owner: https://github.com/giulianotesta7
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@246e7528bc3833b7893d9529fce1c9dbe9f0d06c -
Trigger Event:
push
-
Statement type: