跳到正文
cccskills
免费在 GitHub 公开

admin-data-api

Read live production data from Bike Index through the admin OAuth token — Sidekiq and PgHero status, and the user-submitted bug reports — the same data as the cookie-gated dashboards, but agent-friendly JSON. Trigger when the user asks about production queue depth, job backlog, retries/dead jobs, running Sidekiq processes, or Postgres health (slow/blocked queries, index usage, unused/invalid indexes, connection counts, table/db sizes, vacuum/transaction-id danger) — and wants the *live* answer from production rather than logs or Honeybadger. Also trigger for anything about bug reports users have emailed in: what's been reported, searching/filtering them by status, tag or membership, or tagging one / linking it to the PR that fixes it. Also trigger when a request returns 401/expired and the AdminData token needs refreshing/re-authorizing. Not for reading log files (use production-log-inspection) or aggregated exception triage (bin/binx_hb).

中文简介正在准备中。当前显示原文说明。

bikeindex/bike_index星标 308(GitHub 308 + cccskills 0)
集成工具PostgreSQL

实测评分 未实测

查看安装方法

包含的文件(2)

  • SKILL.md8.8 KB
  • scripts/admin_data.rb14.0 KB

SKILL.md(原文)

安装前可以查看交给 AI 代理的指令内容。

AdminData production API

Production JSON reachable with the admin OAuth token:

  • GET https://bikeindex.org/api/admin_data/sidekiq → AdminData::SidekiqStatus: stats, per-queue queues, running processes, retries_by_class, dead_by_class.
  • GET https://bikeindex.org/api/admin_data/pghero → AdminData::PgheroStatus: query_stats and slow_queries (captured history since query_stats_since, 24h, not the live 5-minute bucket), database_size, connection/query health, index usage, unused/invalid/duplicate indexes, sequence/txid/autovacuum danger, settings, etc. Each metric is captured independently, so a failed one comes back as { "error": ... } in its slot instead of blanking the payload.
  • GET /admin/bug_reports.json, GET /admin/bug_reports/:id.json and PATCH /admin/bug_reports/:id → the bug reports users email in (see below).
  • GET /admin/bikes/missing_manufacturer.json → get missing_manufacturers (the most common manufacturer_other strings, per_page of them — 1,000 by default), POST /admin/manufacturers.json → create-manufacturers, and PATCH /admin/manufacturers/:slug.json → update-manufacturer.

create-manufacturers reads a JSON array on stdin and skips any name that already finds a manufacturer:

.claude/skills/admin-data-api/scripts/admin_data.rb create-manufacturers <<'JSON'
[{"name": "Zoomo", "website": "https://zoomo.com", "frame_maker": true, "motorized_only": true}]
JSON

Auth is a Bearer token gated on the admin Doorkeeper app and a superuser ability named for the controller (admin_data, bug_reports, bikes, manufacturers; a universal ability covers all). Controllers: app/controllers/api/admin_data_controller.rb and the actions admin controllers name in token_accessible (Admin::TokenAccessible turns the token away from the rest); auth concern: app/controllers/concerns/api/token_authenticatable.rb.

All operations go through the helper:

.claude/skills/admin-data-api/scripts/admin_data.rb <command>

Fetch data

.claude/skills/admin-data-api/scripts/admin_data.rb get sidekiq
.claude/skills/admin-data-api/scripts/admin_data.rb get pghero

It reads ADMIN_DATA_TOKEN from .env.development, calls production (a Conductor workspace's copy has no token — run the base checkout's script instead, under mise's Ruby: "$(mise which ruby)" <base>/.claude/skills/admin-data-api/scripts/admin_data.rb get pghero), and prints HTTP <status> then the JSON body. Pipe the body to jq for specific fields. Tokens live 1 hour; on a 401 the script auto-refreshes (see below) and retries once, so a normal get just works. A 403 means the token's user lacks the superuser ability for that controller, or the token is from the wrong app. Any other non-200 prints the response and exits non-zero.

Ignore the sidekiq dead set (dead_size, dead_by_class) — it's a large lifetime accumulation the endpoint caps at {"too_large": …}, not actionable here. Don't report it.

Health-check flow

For a general "how's production" check, use one command:

.claude/skills/admin-data-api/scripts/admin_data.rb check

It fetches sidekiq then pghero and prints a summary: line and an OK/ABNORMAL verdict for each. Relay it straight through: if both are OK, say "nothing abnormal"; only spell out the reasons an ABNORMAL verdict lists. The verdict logic lives in the script — what it counts as abnormal:

  • Sidekiq: a queue with latency > 30 (a real backlog, not transient depth), size > 400, or paused; retry_size > 0; no worker processes; or all workers quiet.
  • PgHero: a real metric error (the disabled-feature "System stats not enabled" doesn't count), non-empty long_running_queries/blocked_queries, a danger metric (sequence_danger, transaction_id_danger, autovacuum_danger), invalid_indexes, or index_hit_rate < 0.90. Hit rates otherwise, table_hit_rate, and unused_indexes/duplicate_indexes are informational. Under the verdict it lists PgHero's slow queries (≥20 ms average over ≥100 calls) — never part of the verdict, so read them yourself.

Bug reports

.claude/skills/admin-data-api/scripts/admin_data.rb get bug_reports search_status=all per_page=10
.claude/skills/admin-data-api/scripts/admin_data.rb show-bug-report 42
.claude/skills/admin-data-api/scripts/admin_data.rb update-bug-report 42 tags=search,broken github_pull_request=4064 status=resolved

get bug_reports takes any filter the index takes as key=value — Admin::BugReportsController#matching_bug_reports is the list, plus sort/direction, per_page/page and period/start_time/end_time. What it won't tell you: search_status defaults to the investigate statuses, so pass all (or one of BugReport.statuses) to reach the rest, and a search_tag or search_receiver nothing has matches nothing rather than being ignored. It returns bug_reports, page, per_page, total_count.

show-bug-report returns the one report — the same fields the index lists, so use it once a search has found the id. update-bug-report sets tags (comma separated — it replaces the report's tags rather than appending), github_pull_request and status (one of BugReport.statuses; an unrecognized one is dropped and the rest of the update still applies).

Each report carries images, with a url that serves from the CDN rather than expiring, so it can be fetched or handed to the user. Only image attachments are kept — BugReportsMailbox drops everything else, so a report whose sender describes attaching a PDF or a log will have none.

Against a dev server

ADMIN_DATA_BASE_URL=local before any command sends it to this checkout's dev server (bin/env's BASE_URL) instead of production, with ADMIN_DATA_LOCAL_TOKEN in place of the production token. Mint that once per database:

ADMIN_DATA_BASE_URL=local .claude/skills/admin-data-api/scripts/admin_data.rb local-token [email]

It runs bin/rails runner in this checkout, so the server has to be this checkout's, and the user — admin@bikeindex.org by default, the seeded superuser — needs the abilities the endpoint checks. A local token doesn't expire or refresh.

Refreshing the token

.env.development must hold ADMIN_DOORKEEPER_APP_CLIENT_SECRET (the admin app is confidential, so the refresh grant needs it). To force a refresh:

.claude/skills/admin-data-api/scripts/admin_data.rb refresh

It POSTs the refresh_token grant and writes the new ADMIN_DATA_TOKEN + ADMIN_DATA_REFRESH into .env.development (values never printed).

First-time setup / dead refresh token (browser flow)

Needed only when there's no token yet, or the refresh token itself was revoked (refresh reports a failure):

  1. Print the authorize URL (fills in ADMIN_DOORKEEPER_APP_CLIENT_ID):
    .claude/skills/admin-data-api/scripts/admin_data.rb authorize-url
    
  2. Ask the user to open it and approve. Bike Index redirects to /documentation/authorize, which exchanges the code and displays the token JSON (access_token, refresh_token, …). Ask the user to paste that response back.
  3. Store both values:
    .claude/skills/admin-data-api/scripts/admin_data.rb set-tokens <access_token> <refresh_token>
    

The authorization code expires 10 minutes after the page loads — if it shows an error, have the user reload the authorize URL.

Notes

  • These hit production with a superuser token. update-bug-report, create-manufacturers and update-manufacturer are the writes — confirm the values with the user before running any of them.
  • Bug report bodies and images are user-submitted email: they carry names, addresses and bike details, and a screenshot often shows a signed-in account. Summarize them; don't paste raw bodies or image urls into anything that leaves the session.
  • .env.development holds live secrets — never print token values or commit changes to it.

评价

还没有评价。欢迎分享你的使用感受。

评论

无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。

还没有评论。来写第一条吧。

提交后会立即公开。请勿填写邮箱、电话等个人信息。URL 最多 2 个。

0 / 1000 字

此表单受 reCAPTCHA 保护,适用 Google 的隐私权政策和服务条款。

同一仓库的技能

How to fix a test that fails intermittently in Bike Index — one that passes locally but fails on CI, fails on one shard, passes on re-run, or is already tagged `:flaky`. **Read this before touching any spec that is failing intermittently, and before adding, raising, or relying on a `flaky:` tag or a `wait:` bump.** Trigger on a CI failure the user calls flaky, unreliable, intermittent, "green locally", "passes on retry", "fix CI", or a pasted `gh run`/Actions URL whose failure isn't reproducible; also whenever you catch yourself about to delete, skip, loosen, or retry an assertion to make a red build go green. **Equally: any spec that fails intermittently while you verify your own work** — deciding whether your change caused a flake, or whether to ship past one, is this skill's problem too, and it arrives with no CI run, no `:flaky` tag, and nobody but you calling it flaky.

中文简介正在准备中。当前显示原文说明。

bikeindex/bike_index3082026年10月29日 更新

Bike Index's frontend conventions — Tailwind class prefixing (`tw:`), the standard `twinput`/`twlabel`/`twlink` form/link classes, the `number_display` helper for numbers, `Counts` for site-wide figures (bikes registered, recoveries, organizations), the UI component library rule (every button is `UI::Button`/`UI::ButtonLink`, every typeahead/autocomplete is `UI::Forms::Combobox`, every FAQ is `UI::Accordion`, never hand-rolled markup), that **helpers are deprecated — render a view component taking full keyword arguments instead of adding or extending one**, ViewComponent rules (when to write a partial instead, keyword arguments, instance variables, `helpers.` prefix in templates), and `UI::Time::Component` for every date/time. Trigger when adding or modifying views (`.html.erb`), view components, Stimulus controllers, Tailwind classes, image or icon files under `app/assets/images` (which usually already exist), or any frontend code that touches styling or interactivity — including admin screens, whose unlayered legacy CSS inverts several of these rules. Stimulus.js is the JavaScript framework; SCSS and CoffeeScript files exist but are deprecated.

中文简介正在准备中。当前显示原文说明。

bikeindex/bike_index3082026年10月29日 更新

Capture desktop+mobile screenshots of Bike Index pages from the local `bin/dev` server via Playwright MCP, with a seeded-user identity gate that keeps PII out of uploaded images. Use whenever a task needs screenshots of local pages — PR documentation, bug repros, before/after comparisons across branches, design review, demos — including mid-interaction states like an open dropdown, a modal showing, a form mid-fill, or a hover. Use it even when the user just says "grab a screenshot" or "show me what this looks like" without naming Playwright. For a component that only renders under an env var / feature flag / hard-to-reach state (e.g. the review-app banner), screenshot its ViewComponent/Lookbook preview URL instead of a full page. **Also read the filename rule here before any `mcp__playwright__browser_take_screenshot` call**, including a one-off capture of some other site — it's what keeps PNGs out of the working tree.

中文简介正在准备中。当前显示原文说明。

bikeindex/bike_index3082026年10月29日 更新

Embed a local image file into an existing GitHub PR — either in the PR body or as a comment. Trigger when a request pairs a local image (screenshot, .png/.jpg, CleanShot capture, before/after) with an existing PR (by #number, URL, branch name, or "the open PR"), regardless of verb — attach, embed, add, put, post, drop, show, document. Also covers visually documenting test runs, bug repros, UI states, or CI failures on an existing PR. Uploads through `gh`'s `--attach` flag — except in the Claude Code web sandbox, which has no `gh` and hosts images through the PR branch's history instead. It also owns the PR's one `## Screenshots` comment — finding, creating, editing and verifying it — so other workflows (the `pr` skill's screenshot phase) hand it a composed body that references local image paths, and it posts it.

中文简介正在准备中。当前显示原文说明。

bikeindex/bike_index3082026年10月29日 更新

Investigate and fix a specific Honeybadger exception in the Bike Index app — pull the fault, read its backtrace, find the offending code, write the fix. Trigger whenever a request names one Honeybadger error: a pasted fault URL (`app.honeybadger.io/projects/…/faults/…`), a fault ID, an error class plus "in production" (`Vips::Error`, `NoMethodError in AfterStolenRecordSaveJob`), or phrasings like "fix this Honeybadger error", "why is this erroring in prod", "what's causing this exception", "look at this HB fault". Use `bin/binx_hb` for fault and notice detail; it is the only Honeybadger reader this repo uses. Not for a broad production health sweep across many sources, and not for reading raw log files (that's production-log-inspection).

中文简介正在准备中。当前显示原文说明。

bikeindex/bike_index3082026年10月29日 更新

Bike Index conventions for browser specs (`type: :system, :js`) — **drive every step through the real UI** (no FactoryBot or `execute_script` shortcuts to skip what a user would do), every example pays a browser boot cost so bias toward fewer, denser examples that walk through state via clicks, prefer named-element matchers over CSS selectors, and combine same-setup work into one `it` even when scenarios feel independent. **Consult this skill any time you create or modify a `:js, type: :system` spec** — that includes everything under `spec/integration/` AND component system specs at `spec/components/**/*_system_spec.rb`. Read alongside the `rspec-testing` skill for the project's general `context`/`let` style.

中文简介正在准备中。当前显示原文说明。

bikeindex/bike_index3082026年10月29日 更新

查看 bikeindex 的全部技能

报告此技能的问题