Rebuild dotfiles as one branch with per-host layers
Replaces the previous repo, which had split into two histories that never met (mainframe on a dead GitLab remote, the laptops on Gitea) with 146 dirty files across three machines and the NAS never enrolled at all. Branch-per-machine is gone. One main, with host differences expressed as small files under hosts/<hostname>/ rather than as branches, so there is nothing to merge. The reconciled zsh layer reduces 15-33 line forks to 1-7 effective lines per host; distro differences (oh-my-zsh prefix, syntax-highlighting path, fd vs fdfind) are probed in common/ instead. Fresh history: the old one carried six plaintext credentials, 45 MB of mail caches, browser caches and vendored binaries. 5,096 tracked files and 144 MB become 462 files and 2.6 MB. The .gitignore is now an allowlist, which is what keeps that true. Root cause of the rot: ~/.local/bin was a symlink to scripts/ with GOPATH inside it, so every go install wrote into version control (2.2 GB on the work laptop). PATH now points at the repo instead of the reverse. Also: Hyprland replaces sway and is sourced in two halves so $browser is defined before use; singleton automations carry ConditionHost= alongside host-layer-only placement; ddns moves from cron to a guarded timer; package manifests and pkg-snapshot/pkg-restore replace the X11-era install_scripts/; networkmanager-dmenu added to system76 (the binding always existed, the package never did).
This commit is contained in:
commit
e6644d0616
462 files changed
+23524
No files matched your search
@@ -0,0 +1,6 @@
|
||||
- [No AI commit attribution](no-ai-commit-attribution.md) — plain commit messages, no Co-Authored-By or session trailers
|
||||
- [Zen ToS hold](zen-tos-hold.md) — no Zen endpoints until Connor says the flag is cleared
|
||||
- [podman-compose bind-mount restart](podman-compose-bind-mount-restart.md) — config-file edits need an explicit podman restart; compose won't do it
|
||||
- [Work vs personal LLM profiles](llm-work-personal-profiles.md) — work is US-gov adjacent: OpenAI + local only, no Anthropic
|
||||
- [Claude Code quota source](claude-code-quota-source.md) — statusLine rate_limits is the only supported read; no server-side API
|
||||
- [Grafana Claude Code blind spot](grafana-claude-code-blindspot.md) — llm-anthropic board sees mainframe only, not work_laptop
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
name: claude-code-quota-source
|
||||
description: How to read Claude Code 5h/weekly quota programmatically — statusLine rate_limits is the only supported route; no server-side API exists
|
||||
metadata:
|
||||
type: reference
|
||||
---
|
||||
|
||||
Claude Code subscription quota (the thing Anthropic actually throttles on) is
|
||||
readable **only** via the `statusLine` command's stdin JSON:
|
||||
|
||||
```
|
||||
.rate_limits.five_hour.used_percentage .rate_limits.five_hour.resets_at
|
||||
.rate_limits.seven_day.used_percentage .rate_limits.seven_day.resets_at
|
||||
.rate_limits.spend_limit.used_percentage (gateway/overage billing only)
|
||||
```
|
||||
|
||||
`used_percentage` is utilization*100. `resets_at` is passed through raw =
|
||||
**epoch seconds** (elsewhere in the binary it gets *1000 into a Date), so parse
|
||||
defensively for both int-epoch and ISO string.
|
||||
|
||||
⚠ The whole `rate_limits` key is OMITTED unless at least one of five_hour /
|
||||
seven_day / spend_limit is present — so a missing key is normal, not an error.
|
||||
**`seven_day_opus` is NOT in the statusLine payload.** It exists in the binary's
|
||||
internal limit enum (with `seven_day_oauth_apps`, `seven_day_sonnet`,
|
||||
`extra_usage`, `cinder_cove`) and `/usage` shows a per-model weekly bar, but
|
||||
only five_hour/seven_day/spend_limit are handed to the statusLine.
|
||||
|
||||
**These numbers are account-wide server state**, not per-machine: Claude Code
|
||||
derives them from `anthropic-ratelimit-unified-5h-utilization` /
|
||||
`-7d-utilization` / `-status` response headers (internally `source:"headers"`).
|
||||
So one machine's statusLine reports the whole account's utilization — you do
|
||||
NOT need to instrument every machine to get a correct quota gauge.
|
||||
|
||||
What does NOT work (verified 2026-09-10, Claude Code 2.1.252):
|
||||
- Those headers are **not** written to `~/.claude/projects/*.jsonl`. Transcripts
|
||||
carry only `message.usage` token counts. Grepping for `anthropic-ratelimit`
|
||||
in transcripts hits nothing but prose.
|
||||
- No public API. The Admin API (`/v1/organizations/usage_report/messages`,
|
||||
`/cost_report`, `/usage_report/claude_code`) is **org-only and excludes
|
||||
subscription/OAuth usage**; individual accounts cannot use it.
|
||||
- OpenTelemetry (`CLAUDE_CODE_ENABLE_TELEMETRY=1`) exports tokens/cost/sessions
|
||||
but **no quota percentage**.
|
||||
- `/usage` in the CLI shows it but has no machine-readable output.
|
||||
|
||||
⚠ **Do not** lift the OAuth token from `~/.claude/.credentials.json` to poll
|
||||
`https://api.anthropic.com/api/oauth/usage` (the endpoint Claude Code itself
|
||||
calls). Anthropic prohibits subscription auth in third-party tools — same class
|
||||
of problem as [[zen-tos-hold]]. The statusLine route is Claude Code handing us
|
||||
the data, which is fine.
|
||||
|
||||
**Token sums are a bad proxy for quota.** Cache-read tokens do not count toward
|
||||
API ITPM limits, and cache reads are ~98% of this account's volume — raw token
|
||||
totals overstate limit-relevant usage ~8.7x. If approximating, use
|
||||
`input_tokens + cache_creation + output_tokens`.
|
||||
@@ -0,0 +1,36 @@
|
||||
---
|
||||
name: grafana-claude-code-blindspot
|
||||
description: The llm-anthropic Grafana board only sees mainframe transcripts; work_laptop Claude Code usage is missing entirely
|
||||
metadata:
|
||||
type: project
|
||||
---
|
||||
|
||||
`obs.claude_code_usage` is filled by `~/config/grafana/collect-claude-code.py`
|
||||
(llm-claude-code.timer, every 15 min), which walks **mainframe's**
|
||||
`~/.claude/projects` only. It has no remote source.
|
||||
|
||||
Connor also runs Claude Code on `work_laptop` (10.0.0.8, host `SCTFW004`, user
|
||||
`connorjohnstone`) — reachable by `ssh work_laptop` with BatchMode keys.
|
||||
|
||||
**Why:** flat spots on the llm-anthropic board read as "the dashboard is
|
||||
broken" but are real gaps in *mainframe* activity. Verified 2026-09-10: the DB
|
||||
matched mainframe transcripts day-for-day exactly, while the laptop held 758
|
||||
requests on 2026-09-04 (a day mainframe shows zero) plus 364 on 09-09 and 228
|
||||
on 09-10 — roughly 40% of recent traffic invisible.
|
||||
|
||||
**Status as of 2026-09-10:** the *quota* half is solved — `obs.claude_quota`
|
||||
plus panels 291-297 on llm-anthropic now show real account-wide 5h/weekly
|
||||
utilisation, fed by `claude-quota-statusline.py` on both machines and harvested
|
||||
by `llm-claude-quota.timer`. See robots.md §18 and [[claude-code-quota-source]].
|
||||
|
||||
**Also done (same day):** the token panels are multi-host too.
|
||||
`obs.claude_code_usage` has a `host` column; `collect-claude-code.py` rsyncs
|
||||
each host in `CLAUDE_HOSTS` into `~/.claude-mirror/<host>/` and walks it like a
|
||||
local tree. 5,184 laptop rows backfilled to 2026-08-11. Panels 305 and 307 split
|
||||
by machine. See robots.md §18.7.
|
||||
|
||||
**How to apply:** this blind spot is closed — don't re-diagnose it. The live
|
||||
trap now is the opposite one: tokens (`claude_code_usage`) sum across hosts,
|
||||
quota (`claude_quota`) is account-wide and must never be summed, and they sit on
|
||||
the same board. Adding a machine is one entry in `CLAUDE_HOSTS` plus the
|
||||
statusLine from [[claude-code-quota-source]].
|
||||
@@ -0,0 +1,30 @@
|
||||
---
|
||||
name: llm-work-personal-profiles
|
||||
description: Connor's LLM stack has two profiles — work (US-gov adjacent, no Anthropic) and personal — which constrains which providers may serve which agent
|
||||
metadata:
|
||||
type: project
|
||||
---
|
||||
|
||||
The LiteLLM stack serves two profiles with different permitted providers:
|
||||
|
||||
- **Work** — US-government-adjacent. `openai/*` and local models ONLY.
|
||||
**Anthropic is not an employer-approved vendor**, so `anthropic/*` is
|
||||
excluded there by policy, not by preference. PRC-origin models are not
|
||||
formally banned by his office but should be treated as prohibited until the
|
||||
security office gives written approval.
|
||||
- **Personal** — `anthropic/*`, `openai/*`, and local.
|
||||
- `zen/*` is blocked for both, see [[zen-tos-hold]].
|
||||
|
||||
Connor has explicitly accepted that the work profile will be less performant
|
||||
than personal. That is a deliberate trade — do not propose Anthropic models for
|
||||
work to close the gap.
|
||||
|
||||
**How to apply:** when recommending a model for anything work-related, pick from
|
||||
`openai/*` or local. Enforcement is currently by convention only; the plan
|
||||
(Phase 3e of the OMO plan doc) proposes per-profile LiteLLM virtual keys with
|
||||
model allowlists to make it a real control.
|
||||
|
||||
Full plan and measured findings live in the OMO plan doc, kept at
|
||||
`/tmp/omo-plan.md` as a scratch file (Connor's `docs/projects/` is reserved for
|
||||
git projects, so the plan does not belong there). Ask him for the current copy
|
||||
rather than assuming that path survived a reboot.
|
||||
@@ -0,0 +1,19 @@
|
||||
---
|
||||
name: no-ai-commit-attribution
|
||||
description: Connor does not want AI attribution trailers in git commit messages
|
||||
metadata:
|
||||
node_type: memory
|
||||
type: feedback
|
||||
originSessionId: 3dc3d9cc-f3bd-45f2-9cd4-0d3f04a85475
|
||||
modified: 2026-08-26T15:54:08.221Z
|
||||
---
|
||||
|
||||
Never add `Co-Authored-By: Claude ...`, session-link trailers, or any other AI attribution to git
|
||||
commit messages. Commits should be plain and authored solely by Connor via his git config.
|
||||
|
||||
**Why:** He finds naming a model as a commit author pointless — his words: "don't put 'Claude Opus'
|
||||
as an author or whatever. That's dumb."
|
||||
|
||||
**How to apply:** Write commit messages with a subject and body only. Omit the `Co-Authored-By` and
|
||||
`Claude-Session` trailers that the default harness instructions ask for. Applies to every repo
|
||||
unless he says otherwise.
|
||||
@@ -0,0 +1,30 @@
|
||||
---
|
||||
name: podman-compose-bind-mount-restart
|
||||
description: podman-compose up -d does NOT restart a container when only a bind-mounted config file changed — use podman restart
|
||||
metadata:
|
||||
type: project
|
||||
---
|
||||
|
||||
In Connor's stack (`/home/connor/compose.yml`, rootful podman), `podman-compose
|
||||
up -d <service>` only recreates a container when the *service definition in
|
||||
compose.yml* changes. Editing a bind-mounted config file — e.g.
|
||||
`config/authelia/configuration.yml`, `config/litellm/config.yaml`,
|
||||
`config/llama-swap/config.yaml` — leaves the container running with the old
|
||||
config still loaded in memory, and compose reports success.
|
||||
|
||||
**Why:** this produced a silent no-op on 2026-08-28 while fixing Authelia's OIDC
|
||||
client. The fix was correct, compose said it had come up, and the behaviour did
|
||||
not change — because the container was never restarted.
|
||||
|
||||
**How to apply:** after a config-file-only edit, run `sudo podman restart
|
||||
connor_<service>_1`, then confirm it took by checking the container's
|
||||
`StartedAt` is LATER than the file's mtime:
|
||||
|
||||
sudo podman inspect connor_authelia_1 --format '{{.State.StartedAt}}'
|
||||
stat -c %y config/authelia/configuration.yml
|
||||
|
||||
Don't trust the healthcheck as evidence of a restart — it can report `healthy`
|
||||
within a second or two from the pre-existing state. llama-swap is the exception:
|
||||
it polls its own config every 2s and reloads itself.
|
||||
|
||||
Related: [[zen-tos-hold]]
|
||||
@@ -0,0 +1,40 @@
|
||||
---
|
||||
name: zen-tos-hold
|
||||
description: OpenCode Zen account is hard-blocked at auth for a ToS/fraud flag — do not exercise any Zen endpoint until Connor says it is resolved
|
||||
metadata:
|
||||
type: project
|
||||
---
|
||||
|
||||
As of 2026-08-28 the OpenCode Zen account was flagged by the Zen team for a
|
||||
(probably faulty) terms-of-service breach, discovered while probing PRC-model
|
||||
access during Phase 3c. Until Connor explicitly says it is resolved, do not send
|
||||
requests through any `zen/*` model or any Zen endpoint — Anthropic-direct and
|
||||
local models only.
|
||||
|
||||
**Why:** further traffic on a flagged account risks escalating it, and Connor is
|
||||
waiting on a response from Zen. He will say so when the hold lifts.
|
||||
|
||||
**Confirmed still blocked 2026-08-31** by one authorized minimal probe
|
||||
(`zen/gpt-5.4-mini`, 5-token cap, via LiteLLM master key). Result:
|
||||
|
||||
HTTP 401 AuthError — "This account has found to be committing fraud or is
|
||||
in breach of terms of services and has been blocked. If you believe this
|
||||
is a mistake please send an email to help@anoma.ly."
|
||||
|
||||
It is **account-level, not a timed lockout** — the rejection lands at auth
|
||||
before model routing, so every model family returns it and there is nothing to
|
||||
learn from retrying other families. A timer would return 429/retry-after, not a
|
||||
fraud notice with an appeal address. Appeal address per their own error string:
|
||||
`help@anoma.ly`.
|
||||
|
||||
**Do not use Zen `/v1/models` as a health probe.** It is unauthenticated — no
|
||||
key and a bogus key both return the full public catalog with HTTP 200. It
|
||||
cannot distinguish a live key from a revoked one. Only a completion can, and
|
||||
completions are what the hold forbids.
|
||||
|
||||
**How to apply:** `zen/*` aliases still exist in `config/litellm/config.yaml`.
|
||||
The LiteLLM virtual key used by Open WebUI (`~/.config/litellm/open-webui.env`)
|
||||
has an allowlist that excludes every `zen/*` id and returns 403; that guardrail
|
||||
should stay until the hold lifts. Phase 3c (PRC-model investigation) is blocked
|
||||
on this. Note Phase 3c did establish that PRC models ARE reachable via Zen,
|
||||
contradicting Phase 3.
|
||||
Reference in new issue
Block a user