v0.2.0: split — public framework only, runbook fetched from private host
The agent and skill prose used to ship inside this package, which exposed home-infra topology (hosts, IPs, AINs, container layout, /opt/herding cred paths) to anyone with the public package URL. This release moves to a fetcher model: - Public package ships only the plumbing: claude-his-fetch + claude-his-install. - Runbook content lives on a private host at $HIS_CONTEXT_HOST:/opt/his-context/. - claude-his-fetch (rsync over SSH) populates ~/.cache/claude-his-agent/. - claude-his-install symlinks ~/.claude/agents/his.md + ~/.claude/skills/his into the cache. History rewritten — the previous tree contained sensitive operational details. A bundle of the pre-rewrite tree is preserved out-of-band by the maintainer.
This commit is contained in:
@@ -0,0 +1,99 @@
|
|||||||
|
# claude-his-agent
|
||||||
|
|
||||||
|
A Claude Code subagent + skill for a personal home-infrastructure assistant
|
||||||
|
("His" — Home Infrastructure Specialist). Designed so a sibling Claude on any
|
||||||
|
host in your fleet can summon a single, consistent infra runbook instead of
|
||||||
|
re-learning your topology every session.
|
||||||
|
|
||||||
|
## Distribution model
|
||||||
|
|
||||||
|
This package ships **only the plumbing** — a fetcher and an installer. The
|
||||||
|
actual runbook (agent prompt + skill cheatsheet) lives on a private host that
|
||||||
|
you control and is pulled into a per-user cache the first time you run
|
||||||
|
`claude-his-install`. None of the infra context is in the public package or
|
||||||
|
its git history.
|
||||||
|
|
||||||
|
```
|
||||||
|
public package (this repo) → /usr/bin/claude-his-fetch
|
||||||
|
/usr/bin/claude-his-install
|
||||||
|
/usr/share/doc/claude-his-agent/README.md
|
||||||
|
|
||||||
|
private host (you set up) → /opt/his-context/agent.md
|
||||||
|
($HIS_CONTEXT_HOST, default hertz) /opt/his-context/skill/SKILL.md
|
||||||
|
/opt/his-context/scripts/...
|
||||||
|
|
||||||
|
per-user cache (after fetch) → ~/.cache/claude-his-agent/
|
||||||
|
~/.claude wiring (after install) → ~/.claude/agents/his.md -> cache/agent.md
|
||||||
|
~/.claude/skills/his -> cache/skill
|
||||||
|
```
|
||||||
|
|
||||||
|
`claude-his-fetch` is a thin `rsync -a -e ssh "$HOST:$PATH" "$CACHE/"`. The
|
||||||
|
trust boundary is your existing SSH key auth on `$HIS_CONTEXT_HOST`.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Debian (trixie/bookworm):
|
||||||
|
sudo apt install claude-his-agent
|
||||||
|
claude-his-install
|
||||||
|
|
||||||
|
# Arch / ALARM:
|
||||||
|
sudo pacman -S claude-his-agent
|
||||||
|
claude-his-install
|
||||||
|
```
|
||||||
|
|
||||||
|
`claude-his-install` runs `claude-his-fetch` if the cache is empty, then
|
||||||
|
symlinks `~/.claude/agents/his.md` + `~/.claude/skills/his` to the cache.
|
||||||
|
|
||||||
|
## Refresh
|
||||||
|
|
||||||
|
Re-run `claude-his-fetch` whenever the runbook on the private host changes.
|
||||||
|
A weekly cron is reasonable:
|
||||||
|
|
||||||
|
```cron
|
||||||
|
0 4 * * 0 $HOME/.local/bin/claude-his-fetch >/dev/null 2>&1
|
||||||
|
```
|
||||||
|
|
||||||
|
(or just call `/usr/bin/claude-his-fetch` from any path the user can read.)
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
| Env var | Default | Purpose |
|
||||||
|
|----------------------|--------------------------------------|---------|
|
||||||
|
| `HIS_CONTEXT_HOST` | `hertz` | SSH target serving the context blob |
|
||||||
|
| `HIS_CONTEXT_PATH` | `/opt/his-context/` | Source dir on the host (trailing slash) |
|
||||||
|
| `HIS_CONTEXT_CACHE` | `~/.cache/claude-his-agent` | Local cache dir |
|
||||||
|
|
||||||
|
`$HIS_CONTEXT_HOST` resolves through the user's `~/.ssh/config` and known_hosts,
|
||||||
|
so an alias like `Host hertz / HostName 192.0.2.10 / User youruser / IdentityFile ~/.ssh/id_ed25519`
|
||||||
|
keeps the rest of the stack hostname-agnostic.
|
||||||
|
|
||||||
|
## Setting up the private host
|
||||||
|
|
||||||
|
On `$HIS_CONTEXT_HOST`, lay out:
|
||||||
|
|
||||||
|
```
|
||||||
|
/opt/his-context/
|
||||||
|
├── agent.md # subagent system prompt (the "take over" form)
|
||||||
|
├── skill/
|
||||||
|
│ └── SKILL.md # skill cheatsheet (the "lookup" form)
|
||||||
|
└── scripts/ # any helpers the runbook references
|
||||||
|
└── ...
|
||||||
|
```
|
||||||
|
|
||||||
|
Owner whichever account the fleet logs in as; mode `0644` for files, `0755`
|
||||||
|
for dirs. The directory does not need to be world-readable — `claude-his-fetch`
|
||||||
|
authenticates as the SSH user.
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
Public framework: `git.reauktion.de/marfrit/claude-his-agent`
|
||||||
|
(this repo — no infra context, safe to mirror).
|
||||||
|
|
||||||
|
Bug reports / runbook gaps for the *private* runbook stay private; for the
|
||||||
|
public plumbing (fetcher, installer, build), file against this repo's issues.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Personal infra tooling; framework code is permissive (see LICENSE if shipped).
|
||||||
|
The runbook content (private) is not redistributable.
|
||||||
Executable
+31
@@ -0,0 +1,31 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# claude-his-fetch — pull current His context from a private host over SSH.
|
||||||
|
# The public package ships zero infrastructure context; the runbook lives on a
|
||||||
|
# host you control and is fetched into a per-user cache that ~/.claude/ symlinks
|
||||||
|
# to. Re-run periodically (cron, or on demand) to refresh.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
HOST="${HIS_CONTEXT_HOST:-hertz}"
|
||||||
|
SRC="${HIS_CONTEXT_PATH:-/opt/his-context/}"
|
||||||
|
CACHE="${HIS_CONTEXT_CACHE:-${HOME}/.cache/claude-his-agent}"
|
||||||
|
|
||||||
|
mkdir -p "${CACHE}"
|
||||||
|
|
||||||
|
echo "claude-his-fetch: ${HOST}:${SRC} -> ${CACHE}"
|
||||||
|
|
||||||
|
if ! command -v rsync >/dev/null 2>&1; then
|
||||||
|
echo "claude-his-fetch: rsync not found; install rsync (apt/pacman) and retry" >&2
|
||||||
|
exit 3
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Reuses the user's existing SSH credentials; trust boundary is whatever
|
||||||
|
# already authorises the user on $HIS_CONTEXT_HOST.
|
||||||
|
rsync -a --delete -e ssh "${HOST}:${SRC}" "${CACHE}/"
|
||||||
|
|
||||||
|
# Sanity — these are the two files ~/.claude symlinks expect to exist.
|
||||||
|
test -r "${CACHE}/agent.md" || { echo "fetch failed: missing agent.md" >&2; exit 2; }
|
||||||
|
test -r "${CACHE}/skill/SKILL.md" || { echo "fetch failed: missing skill/SKILL.md" >&2; exit 2; }
|
||||||
|
|
||||||
|
agent_bytes=$(wc -c <"${CACHE}/agent.md")
|
||||||
|
skill_bytes=$(wc -c <"${CACHE}/skill/SKILL.md")
|
||||||
|
echo "claude-his-fetch: OK (${agent_bytes}B agent, ${skill_bytes}B skill)"
|
||||||
Executable
+26
@@ -0,0 +1,26 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# claude-his-install — wire ~/.claude/{agents,skills}/his to the fetched context cache.
|
||||||
|
# Runs claude-his-fetch first if the cache is empty.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
CACHE="${HIS_CONTEXT_CACHE:-${HOME}/.cache/claude-his-agent}"
|
||||||
|
|
||||||
|
if [ ! -r "${CACHE}/agent.md" ] || [ ! -r "${CACHE}/skill/SKILL.md" ]; then
|
||||||
|
echo "claude-his-install: cache empty, running claude-his-fetch first..."
|
||||||
|
claude-his-fetch
|
||||||
|
fi
|
||||||
|
|
||||||
|
DEST="${HOME}/.claude"
|
||||||
|
mkdir -p "${DEST}/agents" "${DEST}/skills"
|
||||||
|
|
||||||
|
ln -sfn "${CACHE}/agent.md" "${DEST}/agents/his.md"
|
||||||
|
ln -sfn "${CACHE}/skill" "${DEST}/skills/his"
|
||||||
|
|
||||||
|
cat <<EOF
|
||||||
|
Installed His for $USER:
|
||||||
|
${DEST}/agents/his.md -> ${CACHE}/agent.md
|
||||||
|
${DEST}/skills/his -> ${CACHE}/skill
|
||||||
|
|
||||||
|
Refresh by re-running 'claude-his-fetch' (or cron it weekly).
|
||||||
|
Override host/path via HIS_CONTEXT_HOST / HIS_CONTEXT_PATH / HIS_CONTEXT_CACHE.
|
||||||
|
EOF
|
||||||
Reference in New Issue
Block a user