{"id":50243571,"url":"https://github.com/sherodtaylor/agent-smith","last_synced_at":"2026-06-08T02:01:32.609Z","repository":{"id":360117316,"uuid":"1245686275","full_name":"sherodtaylor/agent-smith","owner":"sherodtaylor","description":"Chat-driven AI engineering agents via matrix.org","archived":false,"fork":false,"pushed_at":"2026-05-30T23:41:37.000Z","size":823,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-05-31T00:20:28.140Z","etag":null,"topics":["agentic-ai","agents","ai-agents","autonomous-agents","claude-code","force-multipliers","framework","kubernetes","matrix","sandbox","selfhosted"],"latest_commit_sha":null,"homepage":"https://sherodtaylor.github.io/agent-smith/","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sherodtaylor.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":"docs/roadmap-v1.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-21T13:07:15.000Z","updated_at":"2026-05-30T23:41:41.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/sherodtaylor/agent-smith","commit_stats":null,"previous_names":["sherodtaylor/agent-swarm","sherodtaylor/agent-smith"],"tags_count":23,"template":false,"template_full_name":null,"purl":"pkg:github/sherodtaylor/agent-smith","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sherodtaylor%2Fagent-smith","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sherodtaylor%2Fagent-smith/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sherodtaylor%2Fagent-smith/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sherodtaylor%2Fagent-smith/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sherodtaylor","download_url":"https://codeload.github.com/sherodtaylor/agent-smith/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sherodtaylor%2Fagent-smith/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34044919,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-08T02:00:07.615Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agentic-ai","agents","ai-agents","autonomous-agents","claude-code","force-multipliers","framework","kubernetes","matrix","sandbox","selfhosted"],"created_at":"2026-05-26T22:08:06.655Z","updated_at":"2026-06-08T02:01:32.602Z","avatar_url":"https://github.com/sherodtaylor.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# agent-smith\n\n\u003e **Your secure sandboxed agent workforce — ship in your sleep.**\n\n\u003cp\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/sherodtaylor/agent-smith/main/website/public/sprites/devbot.svg\" width=\"64\" alt=\"DevBot — code agent\" /\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/sherodtaylor/agent-smith/main/website/public/sprites/infrabot.svg\" width=\"64\" alt=\"InfraBot — infra agent\" /\u003e\n\u003c/p\u003e\n\nagent-smith is a framework for running long-lived AI engineering agents that\noperate as peers — they read code, open PRs, review each other's work, and\nlearn from what they ship. Deploy them however you run servers; the reference\ndeployment is one Kubernetes StatefulSet per agent.\n\n---\n\n## What your team can do\n\nEach agent:\n\n- **Owns a persistent workspace** — full filesystem + shell access on a long-lived volume\n  with real cluster credentials. Work carries over across sessions; context isn't lost on\n  restart.\n- **Follows the full engineering workflow** — reads the code, writes the fix, opens the\n  PR, waits for review, addresses comments, merges. The whole loop, autonomously.\n- **Watches its own PRs** — a `Stop`-hook reruns the agent when unaddressed review\n  comments appear. No human prompt required to close the loop.\n- **Coordinates with teammates** — one agent opens a PR, the other reviews it end-to-end\n  and posts inline findings. NATS is the durable audit log for every team action.\n- **Never holds production secrets** — stub tokens are swapped for real credentials at the\n  network boundary by an egress firewall (see [Security](#security--iron-proxy)). A\n  compromised pod can't reach outside the allowlist.\n\nReach them from a Matrix room, from your phone, or via the Claude desktop app. The\ninterface is up to you; the engineering capability is always there.\n\nThe runtime is production-grade: one Kubernetes `StatefulSet` per agent, GitOps-managed\nvia Flux, secrets from Infisical via ExternalSecrets, full observability through\nVictoriaMetrics / VictoriaLogs. These agents ship work that ends up in `main`.\n\n### Why Claude Code CLI (not the Agent SDK, `claude -p`, or an alternative wrapper)\n\nThe interactive CLI is the only option that is long-lived, subscription-billed, and\nMCP-capable at the same time:\n\n- **[Agent SDK](https://support.claude.com/en/articles/15036540-use-the-claude-agent-sdk-with-your-claude-plan)** — billed as Anthropic API tokens, not a Pro/Max subscription. An always-on crew turns a flat monthly cost into a per-token meter.\n- **`claude -p`** — subscription quota, but exits after each response. No persistent state, no warm prompt cache, no MCP handshake.\n- **Alternatives (opencode, etc.)** — you supply the model. Can't drive a Claude subscription.\n\n---\n\n## Under the hood — reference deployment\n\n*The way we run agent-smith. Yours can be different.*\n\nOne image, many agents. The runtime in a single pod looks like this:\n\n```\nStatefulSet/\u003cagent\u003e           (one per agent: infrabot, devbot, …)\n└── init container: setup.sh  (assembles ~/.claude, installs plugin, clones repos)\n└── main container: entrypoint.sh\n    └── tmux session \"main\"\n        ├── pane 0 — claude (channels + --remote-control)  ← receives Matrix messages\n        │                                                    + exposed for remote drive-in\n        └── pane 1 — plain bash shell                       ← ad-hoc inspection on attach\n```\n\n**One image, parametric persona.** Every agent runs `ghcr.io/sherodtaylor/agent-smith:latest`\nwith a different `AGENT_NAME`. At startup `scripts/setup.sh` reads `agents/\u003cAGENT_NAME\u003e/` and\nassembles `~/.claude/` from:\n\n| Source file | Becomes | Purpose |\n|---|---|---|\n| `agents/_shared/CLAUDE.md` + `agents/\u003cname\u003e/CLAUDE.md` (concatenated) | `~/.claude/CLAUDE.md` | base rules + persona |\n| `agents/_shared/settings.json` | `~/.claude/settings.json` | plugins, permissions, hooks |\n| `agents/_shared/.credentials.json` | `~/.claude/.credentials.json` | stub OAuth creds (iron-proxy swaps in real tokens at egress) |\n| `agents/\u003cname\u003e/mcp.json` | `~/.claude/.mcp.json` | per-agent MCP servers |\n| `agents/\u003cname\u003e/subagents/*.md` | `~/.claude/agents/*.md` | persona-specific subagents |\n\n**One claude per pod, channels + remote-control on the same instance.** The entrypoint\nlaunches a single `claude` process with both the Matrix channel plugin\n(`--dangerously-load-development-channels plugin:matrix@claude-code-channel-matrix`) and\n`--remote-control \"${AGENT_NAME}\"`. The same instance owns the Matrix identity *and* is\nremotely drivable — attaching the Claude desktop/web app picks up that named session. The\nsecond tmux pane is just a plain bash shell for ad-hoc inspection when you `tmux attach`.\n\n**Matrix as the channel.** `~/.claude/settings.json` registers the\n[`claude-code-channel-matrix`](https://github.com/zekker6/claude-code-channel-matrix)\nplugin via Claude Code's marketplace mechanism, and `setup.sh` writes the per-agent Matrix\ncredentials and the sender allowlist to `~/.claude/channels/matrix/`. Every permitted\nmessage in a joined room becomes a Claude Code prompt for that agent — no separate\nlistener, no message queue, no per-room wiring. The 👀 reaction the agent posts on\nacknowledgement comes from the same plugin.\n\n**Agents that watch their own PRs.** A `Stop`-hook (`scripts/check-pr-comments.sh`) runs after\nevery turn, queries GitHub for unaddressed review comments on PRs this agent authored, and\nexits `2` to rewake the agent if any are found. The agent then addresses comments without a\nhuman prompt and posts a one-liner back in `#dev`.\n\n**Cross-agent collaboration over Matrix + NATS.** PR notifications and review requests flow\nthrough Matrix mentions (the actual wake signal). NATS is a durable, structured event log\nfor `pr_opened`, `pr_merged`, `incident`, and `task_done` — written for audit and future\nagents to query, not as a trigger.\n\n---\n\n## Repository layout\n\n```\n.\n├── Dockerfile                       # multi-stage: mcp-nats (Go) + claude CLI + bun\n├── .github/workflows/docker.yml     # push-to-main → ghcr.io/sherodtaylor/agent-smith:latest\n├── agents/\n│   ├── _shared/\n│   │   ├── CLAUDE.md                # base rules every agent inherits\n│   │   └── settings.json            # plugins, permissions, hooks, allow/deny\n│   ├── infrabot/\n│   │   ├── CLAUDE.md                # infra persona (k3s, Flux, VictoriaMetrics)\n│   │   ├── mcp.json                 # victoria-metrics, victoria-logs, nats\n│   │   └── subagents/               # DiagnosticsAgent, FluxAuditor, DocWriter, TestWriter\n│   └── devbot/\n│       ├── CLAUDE.md                # dev persona (Go/bash/YAML, PR workflow)\n│       ├── mcp.json                 # nats\n│       └── subagents/               # CodeReviewer, TestWriter\n└── scripts/\n    ├── setup.sh                     # init container: assemble ~/.claude, clone repos\n    ├── entrypoint.sh                # main container: launch tmux + claude (pane 0) + shell (pane 1)\n    └── check-pr-comments.sh         # Stop-hook: rewake on unaddressed PR comments\n```\n\nThe Kubernetes manifests that actually run these pods live in the\n[`sherodtaylor/homelab`](https://github.com/sherodtaylor/homelab) repo under\n`k8s/apps/agent-smith/`. They are intentionally not in this repo, so the agent image is\ndeployable from anywhere.\n\n---\n\n## The agents today\n\n**InfraBot** — homelab infrastructure specialist. Owns the k3s cluster, Flux GitOps, Helm\nreleases, and observability via the VictoriaMetrics/VictoriaLogs MCP servers. Has\nsubagents for diagnostics (`DiagnosticsAgent`), Flux auditing (`FluxAuditor`),\ndocumentation (`DocWriter`), and validation (`TestWriter`).\n\n**DevBot** — software developer across all repos. Implements features, fixes bugs, writes\ntests, and opens PRs. Has subagents for self-review (`CodeReviewer`) and tests\n(`TestWriter`).\n\nBoth agents are peers. They coordinate through Matrix rooms (`#dev`, `#infra`,\n`#general`, `#audit`). NATS JetStream is a shared durable event log they publish to and\nquery on demand — it never wakes them autonomously; Matrix mentions do.\n\n---\n\n## Configuration\n\n### Init container environment variables\n\nSourced from Infisical via ExternalSecrets in the homelab manifests, then handed to\n`scripts/setup.sh` as plain env vars. Secrets are never echoed.\n\n| Variable | Required | Purpose |\n|---|---|---|\n| `AGENT_NAME` | yes | Selects `agents/\u003cAGENT_NAME\u003e/` — must match a directory in the image |\n| `AGENT_REPOS` | yes | Space-separated `owner/name` list; cloned to `/workspace/\u003cname\u003e` |\n| `PRIMARY_REPO` | no (default `homelab`) | Repo basename whose checkout becomes the agent's working directory |\n| `MATRIX_HOMESERVER_URL` | yes | e.g. `https://matrix.lab.sherodtaylor.dev` |\n| `MATRIX_ACCESS_TOKEN` | yes | Matrix login token for the agent |\n| `MATRIX_BOT_USER_ID` | yes | e.g. `@devbot:lab.sherodtaylor.dev` |\n| `MATRIX_ALLOWED_USERS` | no (default `@sherod:lab.sherodtaylor.dev`) | Comma-separated allowlist of senders the agent reacts to |\n| `GITHUB_TOKEN` | yes | **Placeholder** proxy token (`proxy-token-github`); iron-proxy swaps in the real PAT at egress |\n| `IRON_PROXY_CA_CRT` | yes | iron-proxy MITM CA; installed into the system trust store |\n\n\u003e **Claude credentials are no longer an env var.** Earlier versions used `SWARM_CLAUDE_CREDENTIALS` to inject a real OAuth payload at startup, and prior to that a one-shot setup token. Both are gone — see [Claude credentials](#claude-credentials-stub--login-not-setup-token) below.\n\n### Runtime environment variables\n\nRead by `scripts/entrypoint.sh` and (transitively) by the channel plugin / MCP servers:\n\n| Variable | Used by | Purpose |\n|---|---|---|\n| `AGENT_NAME` | entrypoint, logs | identifies the pod in tmux/attach messages |\n| `PRIMARY_REPO` | entrypoint | sets the tmux pane working directory to `/workspace/$PRIMARY_REPO` |\n| `NATS_URL` | `mcp-nats` (per `mcp.json`) | NATS connection string for event publishing |\n\n### AgentConfig anatomy\n\nTo make a new agent, create `agents/\u003cname\u003e/`:\n\n```\nagents/\u003cname\u003e/\n├── CLAUDE.md         # appended after _shared/CLAUDE.md; defines persona, repos, examples\n├── mcp.json          # MCP servers to expose to this agent\n└── subagents/        # optional persona-specific subagents (one .md per subagent)\n    └── *.md\n```\n\nThat is the entire contract. The image picks it up at build time; deploying a new agent is\nadding the directory + a new `StatefulSet` referencing the same image with a different\n`AGENT_NAME`.\n\n### Shared settings (`agents/_shared/settings.json`)\n\nThe shared settings file is what makes runtime behaviour consistent across agents:\n\n- **`enabledPlugins`** — `matrix@claude-code-channel-matrix` (Matrix channel) and\n  `superpowers@claude-plugins-official` (skill framework).\n- **`permissions.defaultMode: \"auto\"`** with a tight allowlist (`Bash(git*)`, `Bash(gh*)`,\n  read-only `kubectl` and `flux`, plus filesystem tools) and explicit denies for\n  `kubectl delete*` and `git push origin main*`.\n- **`hooks.UserPromptSubmit`** — injects a verbosity reminder before every reply so Matrix\n  output stays short.\n- **`hooks.Stop`** — runs `scripts/check-pr-comments.sh` with `asyncRewake: true`; an exit\n  code of `2` rewakes the agent with the rewake message so PR comments don't sit unanswered.\n\n### Claude credentials: stub + login, not setup-token\n\nIn-cluster credentials live in `agents/_shared/.credentials.json`, committed to the repo\nas a **stub** OAuth payload:\n\n```json\n{\"claudeAiOauth\":{\"accessToken\":\"access-token-stub\",\"refreshToken\":\"refresh-token-stub\", ...}}\n```\n\n`setup.sh` copies this file to `~/.claude/.credentials.json` (mode 600). Claude Code reads\nit, treats it as a valid signed-in session, and starts. Every request the CLI makes to\n`*.anthropic.com` then crosses iron-proxy, which sees the literal `access-token-stub`\nstring in the `Authorization` header and rewrites it to the real OAuth token before\nforwarding upstream. The pod itself never sees the real credential, ever.\n\n**Why not a setup token?**\n\n`claude setup-token` (and its older API key flow) is what you use in a development\nenvironment to bootstrap auth. We don't use it in agent-smith because:\n\n- **Setup tokens are short-lived.** They mint a real OAuth pair on first use and embed it\n  in `~/.claude/.credentials.json`. The pod would then be holding a real refresh token —\n  exactly the thing iron-proxy exists to prevent.\n- **They only work interactively.** `claude setup-token \u003ccode\u003e` blocks on a browser flow\n  to get the code in the first place. A headless pod has no browser, so the only path was\n  to copy a credentials.json from a human's machine — which we used to do via\n  `SWARM_CLAUDE_CREDENTIALS` and which had all the rotation/secret-leak problems iron-proxy\n  was meant to solve.\n- **They get rotated by the upstream.** When Anthropic rotates a refresh token mid-flight,\n  the pod's credentials silently expire. With the stub-token flow there is nothing\n  rotating — iron-proxy holds the live credential and refreshes it on its own schedule.\n\n**Bootstrapping auth for a local dev clone.** If you want to drive a `claude` CLI from\nyour own machine against this codebase (without going through iron-proxy), the supported\nflow is interactive:\n\n```bash\nclaude /login\n```\n\nPick the OAuth path, complete the browser flow. That writes a real\n`~/.claude/.credentials.json` on your laptop, and the rest of the repo (settings, MCP\nconfig, channels, hooks) Just Works against it. **Never copy that file into a pod** —\nthat's the exact failure mode the stub + iron-proxy approach was introduced to fix.\n\n---\n\n## Security — iron-proxy\n\nAll agent egress runs through **iron-proxy** at ClusterIP `10.43.100.100`. This is the\n**egress credential firewall**: agents hold only worthless proxy tokens, and iron-proxy\nswaps real secrets in at the network boundary. A leaked agent token is worthless outside\nthe cluster.\n\n- Agents carry `proxy-token-github` (GitHub) and the stub OAuth payload in\n  `agents/_shared/.credentials.json` (`access-token-stub` / `refresh-token-stub`) — literal\n  placeholder strings, never the real GitHub PAT or Claude OAuth tokens. See\n  [Claude credentials](#claude-credentials-stub--login-not-setup-token) for why.\n- iron-proxy MITMs all HTTPS egress, enforces a default-deny domain allowlist, and\n  rewrites `Authorization` headers with the real credentials scoped to each host.\n- Agent DNS is pointed at iron-proxy (`dnsPolicy: None`). In-cluster names\n  (`*.cluster.local`) pass through to CoreDNS so NATS and the Matrix homeserver still\n  resolve normally.\n- The iron-proxy CA cert is distributed to agent pods via ExternalSecret. `setup.sh`\n  installs it into the system trust store with `update-ca-certificates` so `git`, `gh`,\n  and `curl` trust the MITM; the Dockerfile sets `NODE_EXTRA_CA_CERTS` so the Node-based\n  `claude` CLI does too.\n\nThe agent code itself is unaware of any of this — it sends `Authorization:\nBearer proxy-token-github`, iron-proxy turns it into a real PAT, the target site sees a\nnormal request. The blast radius of a compromised agent pod is therefore \"what can be done\nthrough the allowlist\" rather than \"all of the homelab owner's accounts\".\n\n---\n\n## Deployment\n\nThe agent runs in the homelab's `agents` namespace as a `StatefulSet` (one per agent) with:\n\n- a PVC at `/root` for the assembled `~/.claude/` and persistent state,\n- an init container running `scripts/setup.sh` to populate `/root` and `/workspace`,\n- the main container running `scripts/entrypoint.sh` to start tmux,\n- env vars sourced from an `ExternalSecret` backed by Infisical,\n- `dnsPolicy: None` with `dnsConfig.nameservers: [10.43.100.100]` to route through iron-proxy.\n\nManifests live in\n[`sherodtaylor/homelab/k8s/apps/agent-smith/`](https://github.com/sherodtaylor/homelab/tree/main/k8s/apps/agent-smith).\nReconciliation is via Flux; rolling the image is `flux reconcile kustomization agent-smith`.\n\n---\n\n## Operations\n\n### Attach to a running agent\n\nBoth tmux panes are recoverable from a shell on the pod:\n\n```bash\nkubectl exec -it -n agents \u003cagent\u003e-0 -- tmux attach -t main\n# Ctrl-b o  toggles between pane 0 (claude) and pane 1 (shell)\n# Ctrl-b d  detaches without killing anything\n```\n\n**Pane 0** is the single live `claude` process — it owns the Matrix identity *and* is\nexposed for remote drive-in. Typing into it is fine for ad-hoc prompts, but the Matrix\nplugin is the normal input path. Because the same process runs with `--remote-control\n\u003cagent\u003e`, the Claude desktop/web app can connect to that named session and you can drive\nthe agent from your laptop without going through Matrix at all.\n\n**Pane 1** is just a plain `bash` shell in the same `${WORKDIR}` — useful for `kubectl`,\n`git status`, `flux logs`, peeking at `~/.claude/`, anything that doesn't belong in the\n`claude` REPL.\n\n### Build the image locally\n\n```bash\ndocker build -t agent-smith:local .\n```\n\nThe Dockerfile is multi-stage: stage 1 builds [`mcp-nats`](https://github.com/sinadarbouy/mcp-nats)\nfrom source (Go 1.25+), stage 2 produces the runtime image (Debian + `gh`, `kubectl`,\nNode.js + Claude Code CLI, Bun for the channel plugin, the mcp-nats binary).\n\n### CI / image publishing\n\n`.github/workflows/docker.yml` builds via Buildx + GitHub Actions cache and pushes to\n`ghcr.io/sherodtaylor/agent-smith` with the following tagging contract:\n\n| Trigger | Tags published | Use for |\n|---|---|---|\n| push to `main` | `:main`, `:sha-\u003cshort\u003e` | dev / staging — `:main` moves with every merge; `:sha-…` is immutable |\n| git tag `vX.Y.Z` | `:vX.Y.Z`, `:vX.Y`, `:vX`, `:latest` | production — pin to whichever level of mutability you want |\n\n`:latest` only moves on a versioned release, **never on a push to `main`**, so a\nconsumer that pins `:latest` won't get surprise breakage when an in-flight refactor\nlands. The image also carries OCI labels (`org.opencontainers.image.source`,\n`description`, `title`, `licenses`) so it renders properly on the GHCR package page.\n\n**Cutting a release:**\n\n```bash\ngit tag -a v0.1.0 -m \"Release v0.1.0 — …\"\ngit push origin v0.1.0\n```\n\nThe workflow fires on the tag push and produces the four image tags above **and** the\nmatching Helm chart (see below).\n\n### Helm chart\n\nThe chart in [`charts/agent-smith/`](charts/agent-smith) packages a single agent as a\n`StatefulSet` with ServiceAccount + ClusterRole, two PVCs (`~/.claude/`, `/workspace/`),\nand optional iron-proxy DNS routing. The same release workflow that publishes the image\nalso packages the chart and pushes it to GHCR as an OCI artifact:\n\n| Trigger | Chart artifact |\n|---|---|\n| git tag `vX.Y.Z` | `oci://ghcr.io/sherodtaylor/charts/agent-smith:X.Y.Z` + `.tgz` attached to the GH Release |\n\nInstall one agent:\n\n```bash\nhelm install infrabot oci://ghcr.io/sherodtaylor/charts/agent-smith \\\n  --version 0.1.0 \\\n  --namespace agents --create-namespace \\\n  --set agentName=infrabot \\\n  --set matrix.homeserverUrl=https://matrix.example.com \\\n  --set matrix.botUserId='@infrabot:example.com' \\\n  --set nats.url=nats://nats.svc:4222 \\\n  --set existingSecret=infrabot-secrets\n```\n\n`existingSecret` is **required** and must contain `MATRIX_ACCESS_TOKEN`, `GITHUB_TOKEN`,\nand `IRON_PROXY_CA_CRT`. The chart doesn't manage the secret itself — bring your own\n(manual, ExternalSecrets, sealed-secrets, …). Full values reference in\n[`charts/agent-smith/README.md`](charts/agent-smith/README.md).\n\n### Logs\n\nPane output is teed to PID 1's stdout (`tmux pipe-pane … cat \u003e\u003e /proc/1/fd/1`), so\n`kubectl logs` on either container shows both the setup output and the live tmux content.\nVictoriaLogs in the cluster captures the full stream.\n\n### Inspect a Matrix sender allowlist\n\n```bash\ncat ~/.claude/channels/matrix/access.json\n```\n\nTo change it, update `MATRIX_ALLOWED_USERS` in Infisical and restart the pod — `setup.sh`\nregenerates the file on init.\n\n---\n\n## Agent behaviour\n\nThe behavioural contract lives in [`agents/_shared/CLAUDE.md`](agents/_shared/CLAUDE.md)\nand the per-agent files. Highlights worth knowing when you watch the agents work:\n\n- **Response triggers.** An agent responds when (a) its name appears in the message, (b) the\n  sender is `@sherod:lab.sherodtaylor.dev`, or (c) the message is a threaded reply to\n  something the agent said. All other messages get a `👀` reaction and silence.\n- **Loop prevention.** Agents never reply to each other unless directly named; max three\n  consecutive messages per room without a human in between.\n- **Cross-agent PR review.** After opening a PR, the author publishes\n  `swarm.events.pr_opened` to NATS and mentions every other teammate by full Matrix ID in\n  `#dev`. Mentioned agents read the diff, run the `code-review` skill with `--comment` to\n  post inline findings, and post a one-line summary.\n- **Autonomous PR follow-up.** The `check-pr-comments.sh` Stop hook rewakes the author on\n  unaddressed review comments; the agent addresses or replies to each, then posts a\n  one-liner in `#dev`.\n- **Secret handling.** Agents are forbidden from echoing, logging, or returning secret\n  values in Matrix replies. Generated secrets are written directly to their destination.\n\nFor the full set of shared rules see `agents/_shared/CLAUDE.md` (template — operators replace via ConfigMap for production). For per-agent persona examples see `charts/agent-smith/agents/example-infrabot/CLAUDE.md` and `charts/agent-smith/agents/example-devbot/CLAUDE.md` — both are bundled with the chart as starter templates; production personas live in operator-supplied ConfigMaps referenced via the `configMapRef` value on each agent entry.\n\n---\n\n## Adding a new agent\n\n1. Create `agents/\u003cname\u003e/` with `CLAUDE.md`, `mcp.json`, and an optional `subagents/` dir.\n   Use an existing agent as a template — match the section structure.\n2. Build and push the image (CI does this automatically on merge to `main`).\n3. Provision Matrix credentials for the new agent user in Infisical (`MATRIX_ACCESS_TOKEN`,\n   `MATRIX_BOT_USER_ID`).\n4. Add the new `StatefulSet` in `sherodtaylor/homelab/k8s/apps/agent-smith/` referencing the\n   same image with the new `AGENT_NAME` and the right `AGENT_REPOS`.\n5. Reconcile Flux. The pod comes up, joins Matrix, and is ready to be tagged in `#dev` or\n   `#infra`.\n\nThe shared base rules (`agents/_shared/CLAUDE.md`) automatically include the new agent in\nthe cross-agent PR review fan-out — no per-agent code change required, the rules read the\n**Your Team** list at runtime.\n\n---\n\n## License\n\nApache License 2.0 — see [`LICENSE`](LICENSE) for the full text and [`NOTICE`](NOTICE)\nfor the attribution conventions Apache distributions are expected to carry.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsherodtaylor%2Fagent-smith","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsherodtaylor%2Fagent-smith","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsherodtaylor%2Fagent-smith/lists"}