ember-json

GitHub

提供Ember工具的JSON输出模式,用于以编程方式检查Caddy和FrankenPHP状态。支持在脚本、CI/CD流水线或AI代理中查询指标、解析数据、检测错误及自动化监控。

.agents/skills/ember-json/SKILL.md alexandre-daubois/ember

Trigger Scenarios

在脚本中查询Caddy指标 使用jq解析ember JSON输出 编写服务器健康检查脚本 在CI/CD流水线中自动化Caddy监控 等待Caddy就绪状态

Install

npx skills add alexandre-daubois/ember --skill ember-json -g -y
More Options

Non-standard path

npx skills add https://github.com/alexandre-daubois/ember/tree/main/.agents/skills/ember-json -g -y

Use without installing

npx skills use alexandre-daubois/ember@ember-json

指定 Agent (Claude Code)

npx skills add alexandre-daubois/ember --skill ember-json -a claude-code -g -y

安装 repo 全部 skill

npx skills add alexandre-daubois/ember --all -g -y

预览 repo 内 skill

npx skills add alexandre-daubois/ember --list

SKILL.md

Frontmatter
{
    "name": "ember-json",
    "description": "Use Ember's JSON output to programmatically inspect Caddy and FrankenPHP state from scripts, CI pipelines, or AI coding agents. Use this skill whenever someone wants to query Caddy metrics from the command line, parse ember output with jq, write a script that checks server health, detect 5xx errors programmatically, compare metrics before and after a deployment, use ember in a CI\/CD pipeline, automate Caddy monitoring, or wait for Caddy readiness in a script. Also trigger when an AI agent needs to inspect the current state of a Caddy server: ember's JSON mode is the tool for that."
}

Ember JSON & Scripting

Ember's --json flag turns the dashboard into a machine-readable data source. Instead of the interactive TUI, it outputs one JSON object per polling interval to stdout (perfect for scripts), CI pipelines, and AI agents that need to inspect Caddy/FrankenPHP state programmatically.

Getting a snapshot

# Single snapshot, then exit
ember --json --once

# Streaming mode (one JSON line per second)
ember --json

# Custom interval
ember --json --interval 5s

Errors go to stderr, so stdout is always valid JSONL. This matters when piping to jq or other tools.

Important caveat: derived metrics (RPS, average latency, percentiles) are computed from the delta between two consecutive polls. With --once, there is no previous poll, so derived fields will be zero. Use streaming mode (ember --json without --once) if you need derived metrics.

JSON schema

Each JSON line contains:

{
  "threads": {
    "threadDebugStates": [...],
    "reservedThreadCount": 0
  },
  "metrics": {
    "totalThreads": 0,
    "busyThreads": 0,
    "queueDepth": 0,
    "workers": {},
    "httpRequestsTotal": 0,
    "httpRequestDurationSum": 0,
    "httpRequestDurationCount": 0,
    "httpRequestsInFlight": 0,
    "hasHttpMetrics": true,
    "hosts": {}
  },
  "process": {
    "pid": 12345,
    "cpuPercent": 2.5,
    "rss": 52428800,
    "createTime": 1710000000000,
    "uptime": 3600000000000
  },
  "fetchedAt": "2026-03-16T10:00:00Z",
  "errors": [],
  "derived": {
    "rps": 150.5,
    "avgTime": 12.3,
    "p50": 8.0,
    "p95": 25.0,
    "p99": 80.0
  },
  "hosts": [
    {
      "host": "example.com",
      "rps": 100.2,
      "avgTime": 10.5,
      "inFlight": 3,
      "p50": 7.0,
      "p90": 15.0,
      "p95": 22.0,
      "p99": 75.0,
      "statusCodes": { "200": 95.0, "404": 3.0, "500": 2.0 },
      "methodRates": { "GET": 80.0, "POST": 20.0 }
    }
  ]
}

Field reference

Field Description
threads Raw FrankenPHP thread debug states. Empty object if Caddy-only (no FrankenPHP).
metrics Raw Caddy and FrankenPHP metrics from the admin API. Includes hasHttpMetrics to confirm metrics are flowing.
process Monitored process info: PID, CPU %, RSS in bytes, creation time (Unix ms), uptime (nanoseconds).
fetchedAt Timestamp of this poll in RFC 3339 format.
errors Array of error strings from this poll. Omitted when empty.
derived Computed metrics: RPS, average response time (ms), error rate. Omitted on the first poll.
derived.errorRate Middleware errors per second. Omitted when 0.
derived.p50/p95/p99 Request duration percentiles in milliseconds. Omitted when unavailable.
hosts Per-host breakdown. Omitted when no host-level data exists.
hosts[].statusCodes Map of HTTP status code to request rate (req/s).
hosts[].methodRates Map of HTTP method to request rate (req/s).
hosts[].errorRate Middleware errors/s for this host. Omitted when 0.
hosts[].ttfbP50/P90/P95/P99 Time-to-First-Byte percentiles in ms. Omitted when unavailable.
hosts[].avgRequestSize Average request body size in bytes. Omitted when 0.

Common scripting patterns

Inspect current state

# Overall RPS
ember --json --once | jq '.derived.rps'

# CPU usage
ember --json --once | jq '.process.cpuPercent'

# RSS in MB
ember --json --once | jq '.process.rss / 1048576'

# List all hosts
ember --json --once | jq -r '.hosts[].host'

# Per-host RPS
ember --json --once | jq -r '.hosts[] | "\(.host): \(.rps) rps"'

Detect problems

# Check if any host has 5xx errors
ember --json --once | jq -e '.hosts[] | select(.statusCodes["500"] > 0)'

# Find hosts with high latency (P99 > 100ms)
ember --json --once | jq -r '.hosts[] | select(.p99 > 100) | "\(.host): P99=\(.p99)ms"'

# Check if error rate is above threshold
ember --json --once | jq -e '.derived.errorRate > 0.5'

Monitor over time

# Watch RPS in real time
ember --json | jq -r '.derived.rps'

# Log to file at 5s intervals
ember --json --interval 5s >> ember.log

# Extract per-host 5xx rates continuously
ember --json | jq -r '.hosts[] | "\(.host): \(.statusCodes["500"] // 0)/s"'

Health check: ember status

For a quick one-line check without parsing JSON:

ember status
# Caddy OK | 5 hosts | 450 rps | P99 12ms | CPU 3.2% | RSS 48MB | up 3d 2h

For machine-readable output:

ember status --json

Returns:

{
  "status": "ok",
  "hosts": 5,
  "rps": 450,
  "p99": 12.3,
  "cpuPercent": 3.2,
  "rssBytes": 50331648,
  "uptime": "3d 2h",
  "frankenphp": { "busy": 8, "total": 20, "workers": 2 }
}

Exit code 0 means Caddy is reachable, 1 means unreachable. This makes ember status usable as a health gate in scripts.

Readiness gate: ember wait

Block until Caddy's admin API is reachable:

ember wait --timeout 30s && echo "Caddy is up"

Useful in startup scripts and CI:

# Wait for Caddy after docker-compose up
docker compose up -d && ember wait --timeout 30s && ember status

# Silent mode (exit code only, no output)
ember wait -q --timeout 10s

Exit code 0 means Caddy is ready, 1 means timeout expired.

Deployment validation: ember diff

Compare two JSON snapshots to detect performance regressions:

# Capture before
ember --json --once > before.json

# ... deploy, migrate, change config ...

# Capture after
ember --json --once > after.json

# Compare
ember diff before.json after.json

Sample output:

Global
    Requests             1720 -> 2023        +17.6%
    Avg (cumul.)       76.9ms -> 77.7ms      +1.0%
    Errors                  0 -> 0           =
    In-flight             3.0 -> 1.0         -66.7%

Per-host changes
  api
    In-flight             3.0 -> 1.0         -66.7%

No regressions detected

Exit codes:

  • 0: No regressions detected
  • 1: Regressions found (>10% degradation on latency, error rate, or CPU; >10% drop on RPS)

This makes ember diff a natural CI gate:

ember diff before.json after.json || exit 1

CI pipeline example

#!/bin/bash
set -e

# Wait for Caddy to be ready
ember wait --timeout 30s

# Capture baseline
ember --json --once > before.json

# Deploy new version
./deploy.sh

# Wait for new version to stabilize
ember wait --timeout 30s
sleep 10

# Capture post-deploy state
ember --json --once > after.json

# Check for regressions
ember diff before.json after.json

Version History

  • 2e1a953 Current 2026-07-25 08:03

Same Skill Collection

.agents/skills/ember-production/SKILL.md
.agents/skills/ember-troubleshoot/SKILL.md
.agents/skills/ember-setup/SKILL.md

Metadata

Files
0
Version
2d3ed1d
Hash
5b664cfc
Indexed
2026-07-25 08:03

Accueil - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-08-27 21:25
浙ICP备14020137号-1 $Carte des visiteurs$