From 5131e9f823cabc3f9a5119746e1ffdea1f9d1b22 Mon Sep 17 00:00:00 2001 From: claude Date: Wed, 5 Aug 2026 19:27:58 +0200 Subject: [PATCH] =?UTF-8?q?doc:=20tool-parity=20plan=20=E2=80=94=20Gemini?= =?UTF-8?q?=20CLI=20vs=20Claude=20Code=20gap=20analysis=20+=20homelab=20ad?= =?UTF-8?q?min=20tool=20specs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- README.md | 9 ++ doc/plan.md | 20 ++++ doc/tool-parity.md | 236 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 265 insertions(+) create mode 100644 doc/tool-parity.md diff --git a/README.md b/README.md index b7194d0..d5fbf8b 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,15 @@ agent understands the result without opening an image viewer. Each tool has its own folder, its own README with the full format/CLI reference, its own tests and its own dev branch (`dev/`). +## Planned: agent-capability & homelab-admin tools + +[`doc/tool-parity.md`](doc/tool-parity.md) compares Gemini CLI's +built-in tools with Claude Code's, and specs the CLI tools that close +the gaps (`notifyr`, `giteactl`, `waitfor`, `cronr`, `fleet`, +`envaudit`, `reghelper`, `pagepub`, `nbcell`, `wtreectl`, `fanout`) so +any agent gets the same capabilities via `run_shell_command`. Build +order and rationale live there and in [`doc/plan.md`](doc/plan.md). + ## Building ```bash diff --git a/doc/plan.md b/doc/plan.md index 1657977..e470253 100644 --- a/doc/plan.md +++ b/doc/plan.md @@ -37,6 +37,26 @@ master/main. Only tools whose folders changed get rebuilt. - New tools: bitmap-font maker, sound-effect generator (sfxr-style text presets), tiled-map (.tmx) writer. +### Agent-capability tools (see [tool-parity.md](tool-parity.md)) + +Close the gap between Gemini CLI and Claude Code, plus homelab admin +tools grounded in infra-Doc history. Suggested order: + +1. `notifyr` — send/read on the existing Pi5 ntfy bus (≈ PushNotification). +2. `giteactl` — Gitea Actions runs, zst CI logs, `wait`/`wait-quiet` + build serialization, releases. +3. `waitfor` — block until a condition holds (≈ Monitor); + `cronr` — systemd-user-timer scheduling (≈ CronCreate/List/Delete). +4. `fleet` — one-shot homelab health snapshot via the read-only + claude-docker wrapper. +5. `envaudit` — compose ↔ `.env` key/inline-secret audit; + `reghelper` — registry catalog + prune *plans*; + `pagepub` — publish HTML/MD report to a URL (≈ Artifact); + `nbcell` — Jupyter cell editing (≈ NotebookEdit); + `wtreectl` — disposable git worktrees. +6. `fanout` — parallel headless-agent orchestration (≈ Workflow); only + on concrete need. + ## Open questions - Versioned releases (`vX.Y.Z` tags per tool) on top of the rolling diff --git a/doc/tool-parity.md b/doc/tool-parity.md new file mode 100644 index 0000000..ce7a8e9 --- /dev/null +++ b/doc/tool-parity.md @@ -0,0 +1,236 @@ +# Tool parity: Gemini CLI vs Claude Code + +Goal: let Gemini CLI (the agent driven via `agent-helm`) do everything +Claude Code can, by building the missing capabilities as small CLI tools +in this repo. Gemini calls them through `run_shell_command`, so every +tool follows the house rules: **text in, verifiable artifacts out**, +single static Go binary, self-explanatory output. + +Sources: Gemini CLI tools reference (), +Claude Code's toolset as of 2026-08. + +## 1. Already at parity — nothing to build + +| Capability | Claude Code | Gemini CLI | +|---|---|---| +| Read/write/edit files | `Read` / `Write` / `Edit` | `read_file` / `write_file` / `replace` | +| Find files / search text / list dirs | `Glob` / `Grep` | `glob` / `grep_search` / `list_directory`, plus `read_many_files` | +| Shell, incl. background processes | `Bash` (+ background tasks) | `run_shell_command` (+ background processes) | +| Web | `WebFetch` / `WebSearch` | `web_fetch` / `google_web_search` | +| Ask the user a structured question | `AskUserQuestion` | `ask_user` | +| Plan mode | `EnterPlanMode` / `ExitPlanMode` | `enter_plan_mode` / `exit_plan_mode` | +| Skills / slash commands | `Skill` (`.claude/skills`) | `activate_skill` (`.gemini/skills`) | +| Persistent memory | file-based memory dir | `save_memory` (simpler, but exists) | +| Todo/task tracking | `TaskCreate`/`TaskUpdate`/… | `write_todos`, `tracker_*` (experimental) | +| MCP servers + resources | MCP tools, `ListMcpResources`/`ReadMcpResource` | MCP tools, `list_mcp_resources`/`read_mcp_resource` | +| Subagents | `Agent` (background, custom types) | subagents (experimental) — weaker, see `fanout` below | + +Not worth replicating (harness-internal to Claude Code, no value as a +CLI): `ToolSearch`, `EndConversation`, `ReportFindings`, +`ShareOnboardingGuide`, `DesignSync`, remote cloud execution. + +## 2. Gaps → tools to build + +Ordered by expected value. Each becomes its own folder + binary + +README, per repo convention. + +### 2.1 `cronr` — scheduled/recurring runs *(Claude: `CronCreate`/`CronList`/`CronDelete`, `/loop`)* + +Gemini CLI has no way to schedule work. `cronr` manages **systemd user +timers** so an agent can create recurring or one-shot scheduled jobs +(including "run this prompt every morning" via `gemini -p …`). + +``` +cronr add nightly-ci-check --schedule "*-*-* 07:00" --cmd 'gemini -p "check CI status and notify"' +cronr add once-reboot-check --at "2026-08-06 03:00" --cmd '…' # one-shot +cronr list # name, schedule, next run, last result +cronr logs nightly-ci-check # journalctl for the unit +cronr rm nightly-ci-check +``` + +Output prints the generated unit files so the result is verifiable. +No daemon of its own — systemd does the running. + +### 2.2 `waitfor` — block until a condition holds *(Claude: `Monitor`)* + +Turns "poll every N seconds" into a single blocking tool call, so the +agent doesn't burn turns polling. + +``` +waitfor --cmd "curl -sf https://gitea.brasse-pc.eu/api/healthz" --interval 30s --timeout 20m +waitfor --cmd "ssh pi5 docker ps --format '{{.Names}}'" --matches 'gitea' --timeout 10m +waitfor … --then 'notifyr send --msg "gitea is back up"' +``` + +Exit 0 = condition met, exit 3 = timeout; last output is printed either +way. `--then` runs a command on success (composes with `notifyr`). + +### 2.3 `notifyr` — push notifications, send **and read** *(Claude: `PushNotification`)* + +The ntfy server **already runs on the Pi5** and is the house-wide +notification bus (topics like `Info`, `pi5-server-fel`, `ci-fel` — see +infra-Doc `services/observability.md`). `notifyr` is a thin client so +every agent uses it the same way: + +``` +notifyr send --topic ci-fel --title "Build failed" --msg "agent-tools arm64 test: FAIL" --priority high +notifyr read --topic pi5-server-fel --since 2h # poll mode: what has alerted lately? +``` + +`read` (ntfy's `?poll=1&since=…`) is the underrated half: it lets an +agent *check what the infra has been complaining about* before/after a +change. Config (`~/.config/notifyr/config.json`): server URL + token. + +### 2.4 `pagepub` — publish an HTML/Markdown report to a URL *(Claude: `Artifact`)* + +Claude Code can publish reports as web pages; Gemini cannot. `pagepub` +rsyncs a file to a static-file host on the Pi5 (nginx container behind +NPM, e.g. `pages.brasse-pc.eu`) and prints the stable URL. + +``` +pagepub publish report.html --slug ci-report → https://pages.brasse-pc.eu/ci-report/ +pagepub publish notes.md --slug pi5-audit # .md rendered to HTML with built-in template +pagepub list | rm +``` + +Requires the static host to exist first (small infra task; goes in +infra-Doc + NPM proxy host via `npmctl`). + +### 2.5 `nbcell` — Jupyter notebook editing *(Claude: `NotebookEdit`)* + +`.ipynb` is JSON that's miserable to edit via `replace`. `nbcell` +exposes cells as text: + +``` +nbcell list nb.ipynb # index, type, first line, exec count +nbcell show nb.ipynb 3 # cell source (and outputs with --outputs) +nbcell edit nb.ipynb 3 --from-file cell.py +nbcell add nb.ipynb --at 4 --type code --from-file new.py +nbcell rm nb.ipynb 7 +``` + +### 2.6 `wtreectl` — disposable git worktrees *(Claude: worktree isolation for agents)* + +Claude Code can give each subagent an isolated git worktree. `wtreectl` +does the same for any agent: + +``` +wtreectl new [--branch dev/foo] # prints the new worktree path +wtreectl list +wtreectl clean # removes worktrees with no changes +``` + +Lets two agent sessions work in the same repo without trampling each +other. + +### 2.7 `fanout` — parallel subagent orchestration *(Claude: `Workflow`, `Agent`)* — roadmap, not agreed + +Runs N prompts as parallel headless agent processes (`gemini -p` / +`claude -p`) with a concurrency cap, collecting each result as JSON in +an output dir. A poor man's `Workflow`: + +``` +fanout run jobs.json --max 3 --out results/ +``` + +Heavier than the other tools and overlaps with agent-helm's territory — +park until there's a concrete need. + +## 3. Suggested tools from infra history + +Grounded in what the agent has already been doing per infra-Doc +(`maintenance-and-gaps.md`, `services/source-control-and-deploy.md`, +`services/observability.md`, the per-service "operational quick-ref" +blocks). These help **any** agent (Claude or Gemini) administer the +fleet, and they respect the read-only sudo policy +(`ssh/claude-sudo-policy.md`): everything below is read-or-notify; +mutations still go through Björn's supervised tmux flow. + +### 3.1 `giteactl` — Gitea repos, Actions runs and CI logs + +The biggest recurring friction. Today: CI status is polled ad hoc, and +logs for private repos are only readable as zst files under +`/srv/storage1/gitea/actions_log/…` on the Pi5. Wraps the Gitea REST + +Actions API: + +``` +giteactl runs [--limit 5] # status, branch, duration +giteactl log [--job N] # fetches + decompresses the zst log +giteactl wait [--timeout 30m] # block until latest run finishes; exit 0 = green +giteactl wait-quiet [--max-active 1] # block until ≤N heavy builds are running +giteactl release [] # rolling-release assets + checksums +``` + +`wait-quiet` encodes the hard-learned rule "serialize pushes — >2 heavy +builds take the Pi5 down": `giteactl wait-quiet && git push`. +Composes with `waitfor`/`notifyr`. + +### 3.2 `fleet` — one-shot health snapshot of the whole homelab + +Every service doc ends with the same hand-rolled loop over +`ssh pi5-claude sudo claude-docker ps/inspect …`. `fleet` does that +loop once, properly: + +``` +fleet status # containers (state, image, restarts), disk/mergerfs fill %, failed systemd units +fleet status --host brasse-linux01 +fleet checks # Uptime Kuma monitor states + last ntfy alerts (via notifyr read) +``` + +Read-only by construction (claude-docker wrapper + sudo allowlist), so +it needs no new permissions. Output is a stable text table an agent can +diff between runs. + +### 3.3 `envaudit` — compose ↔ `.env` key auditor + +Grounded in a real incident (`${STORAGE1}` undefined in `/srv/.env` → +bad mount, rollback) and in maintenance-and-gaps' inline-secret +findings: + +``` +envaudit check /srv/dockge-staks --env /srv/.env + → UNDEFINED ${STORAGE1} used by media-stack/compose.yaml + → INLINE LDAP_ADMIN_PASSWORD hardcoded in openldap/compose.yaml (should live in .env) + → UNUSED OLD_API_KEY defined but referenced nowhere +``` + +Pure text analysis of compose files — safe to run anywhere, catches the +two failure classes that have actually happened. + +### 3.4 `reghelper` — docker-registry catalog & hygiene + +The LAN registry (`192.168.0.19:5000`) has no UI, no auth and no +cleanup story, and the backup plan explicitly wants it slimmed: + +``` +reghelper ls # catalog + tags + image sizes +reghelper tags +reghelper prune-plan --keep 2 # prints the delete+GC commands (does NOT run them) +``` + +`prune-plan` deliberately only *prints* the mutation commands for the +supervised tmux flow — same pattern as the sudo policy. + +### 3.5 Backup status reader — once Backrest/restic exists + +future-plans.md has the whole Backrest+restic design chosen but +unbuilt. When it lands, a `fleet backups` subcommand (last snapshot age +per source, repo size, last check result) closes the loop — an agent +can then *verify* backups instead of trusting them. Not a separate +tool; park under `fleet`. + +### Cross-reference + +`/home/brasse/repos/dify-agent-tools/` already has a specced-but-unbuilt +set of FastAPI tools (file/image sorting, face recognition, ST-card +export…) for the Dify platform. Different runtime (HTTP tools vs CLI +binaries), same philosophy — don't duplicate those here. + +## 4. Suggested build order + +1. `notifyr` — smallest, everything else composes with it, ntfy already runs. +2. `giteactl` — removes the biggest daily friction (CI logs + build serialization). +3. `waitfor` + `cronr` — turns both agents into unattended operators. +4. `fleet` — replaces the hand-rolled health loops in every runbook. +5. `envaudit`, `reghelper`, `pagepub`, `nbcell`, `wtreectl` — as needed. +6. `fanout` — only if a concrete multi-agent need shows up.