Self-hosted guidance distribution for coding agents
Project description
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: packs are immutable SemVer releases assigned to projects.
- Keep repos deterministic: each workspace records
.agh/lock.tomland applies only the selected agent target. - Run it yourself: host the server with Docker, SQLite, and persistent
/datastorage.
Install
Linux / macOS:
brew install giulianotesta7/tap/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
Then log in from your machine:
agh login \
--url <instance-url> \
--email owner@example.com \
--token "<initial-owner-token>"
Check the saved config. AGH masks the token:
agh config show
Create a project with the repo URL developers use in git remotes:
agh project create "Agent Guidance Hub" \
--repo-url https://github.com/giulianotesta7/AgentGuidanceHub.git
Work from a linked repo:
agh sync
agh agent select opencode # or: agh agent select claude
agh pull --dry-run
agh pull
agh agent
agh agent show
How AGH works
Pack author ── publish ──▶ AGH server ── assign ──▶ Project
│ │
│ ▼
SQLite + /data Repo workspace
│
├─ AGENTS.md + .opencode/skills/
└─ CLAUDE.md + .claude/skills/
| Piece | What it does |
|---|---|
| Packs | Shared instructions, skills, or both. Published versions are immutable. |
| Projects | One git repository plus the pack versions it should use. |
| Workspaces | A local repo linked with agh sync, one selected agent, and a committed lockfile. |
Pack authoring
A pack starts with this shape:
my-pack/
├── agh.pack.toml
├── instructions/
│ ├── AGENTS.md
│ └── CLAUDE.md
└── skills/
└── reviewer/
└── SKILL.md
Create a template:
agh pack init ./my-pack --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.pack.tomlinstructions/AGENTS.mdinstructions/CLAUDE.mdskills/<name>/SKILL.md
Rules:
- A pack 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 packs to projects. - Use UTF-8 text files. Do not include symlinks.
Publish and list packs:
agh pack publish ./my-pack
agh pack list
Example publish output:
Published acme/onboarding@1.0.0.
Pack ID: pack_...
Checksum: sha256:...
Project assignment
A project is an AGH record linked to one git repository.
agh project create "Agent Guidance Hub" \
--repo-url https://github.com/giulianotesta7/AgentGuidanceHub.git
agh project list
agh project get prj_...
agh project update prj_... --name "App API"
agh project delete 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 packs to a project:
agh project pack add prj_... acme/onboarding@latest
agh project pack add prj_... onboarding@1.0.0
agh project pack list prj_...
agh project pack update prj_... asn_... --pack-ref acme/onboarding@1.0.0
agh project pack remove prj_... asn_...
asn_... identifies the project-to-pack assignment. Pack inputs accept packv_..., domain/name@version, and exact name@version refs. No-domain refs must match a single pack 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.
During workspace pull, AGH writes the resolved concrete version and checksum to .agh/lock.toml.
Workspace pull and Git state
| Command | What it does |
|---|---|
agh sync |
Matches the git remote to an AGH project and writes .agh/project.toml. |
agh agent / agh agent show |
Shows Claude Code/OpenCode availability and the current local selection. |
agh agent select claude |
Selects Claude Code for this workspace. |
agh agent select opencode |
Selects OpenCode for this workspace. |
agh agent clear |
Removes the local workspace agent selection. |
agh pull --dry-run |
Fetches the server plan without writing repo files. |
agh pull |
Applies instructions and skills for the selected agent and writes .agh/lock.toml. |
agh pull --force |
Replaces conflicted AGH blocks or skill targets. |
There is no both option. If no agent is selected, interactive agh pull asks which agent to use. Skip exits with code 2 and writes nothing.
Instruction files use managed blocks:
<!-- AGH-BEGIN pack="<pack-ref>" artifact="instructions/AGENTS.md" checksum="sha256:..." -->
Project instructions from AGH live here.
<!-- AGH-END pack="<pack-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/packs/.... If the OS rejects symlinks, AGH copies the file. The lockfile records the mode:
mode = "symlink" # or mode = "copy"
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 packs to .agh-cache/packs/ and stores each developer's agent 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 agent selection. |
3 |
Conflict. |
4 |
Authentication/authorization failure. |
5 |
Workspace is not linked; run agh sync. |
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, packs, and assignments. |
member |
Day-to-day workspace access. |
Admin commands:
agh user list
agh user create user@example.com --role admin
agh user show user@example.com
agh user update usr_... --role member
agh user delete usr_...
agh token rotate
agh token reset usr_...
agh config show
User commands that take a user reference accept usr_... ids or exact emails.
agh config show masks the saved token as token = ****.
Runtime state lives under /data:
| Path | Purpose |
|---|---|
/data/agh.sqlite3 |
SQLite database. |
/data/packs/ |
Published pack payloads. |
/data/logs/agh.log |
Server log. |
/data/secrets/initial_owner_token |
First owner token, created once. |
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/packs/
/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:
Project details
Release history Release notifications | RSS feed
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.3.0.tar.gz.
File metadata
- Download URL: agh-0.3.0.tar.gz
- Upload date:
- Size: 298.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
10597c78f2e1bc59fe4f49975ab6fb04be868fdbc1137182a750f17bf7abdf59
|
|
| MD5 |
2e8999e2b8abeed4c8568b97ced400ea
|
|
| BLAKE2b-256 |
df40d74398768b5394eb0b2b7f28229151c332166ba8ba56a32f18a661c1d31a
|
Provenance
The following attestation bundles were made for agh-0.3.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.3.0.tar.gz -
Subject digest:
10597c78f2e1bc59fe4f49975ab6fb04be868fdbc1137182a750f17bf7abdf59 - Sigstore transparency entry: 1803975252
- Sigstore integration time:
-
Permalink:
giulianotesta7/AgentGuidanceHub@edb81d6dc56ddee22351ee70eaa42a827372b0da -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/giulianotesta7
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@edb81d6dc56ddee22351ee70eaa42a827372b0da -
Trigger Event:
push
-
Statement type:
File details
Details for the file agh-0.3.0-py3-none-any.whl.
File metadata
- Download URL: agh-0.3.0-py3-none-any.whl
- Upload date:
- Size: 63.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dd1074023a5cfa826570205ad1d167f46c39de7a0fde746af216884d97f05d6c
|
|
| MD5 |
8498e70412ffcbe638c021b83a1e7359
|
|
| BLAKE2b-256 |
ce5223f1d85f13d044d8cec730cea2927e67364e20119b3c8bff170a0201f700
|
Provenance
The following attestation bundles were made for agh-0.3.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.3.0-py3-none-any.whl -
Subject digest:
dd1074023a5cfa826570205ad1d167f46c39de7a0fde746af216884d97f05d6c - Sigstore transparency entry: 1803975477
- Sigstore integration time:
-
Permalink:
giulianotesta7/AgentGuidanceHub@edb81d6dc56ddee22351ee70eaa42a827372b0da -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/giulianotesta7
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@edb81d6dc56ddee22351ee70eaa42a827372b0da -
Trigger Event:
push
-
Statement type: