Gaggiuino Local

v3.1.0

Gaggiuino skill for machine control, espresso shot analysis through profile intent, dial-in guidance, shot graph rendering, and synchronized overlay videos....

0· 257·0 current·0 all-time
byzazack@zackzmai
MIT-0
Download zip
LicenseMIT-0 · Free to use, modify, and redistribute. No attribution required.
Security Scan
VirusTotalVirusTotal
Benign
View report →
OpenClawOpenClaw
Benign
high confidence
Purpose & Capability
Name/description (Gaggiuino local machine control, shot analysis, graph/video rendering) match what the files do: the scripts call curl to a local HTTP API, run Python-based renderers, and use ffmpeg/ffprobe for video. Required binaries (curl, python3, mktemp, ffmpeg, ffprobe) are appropriate and expected.
Instruction Scope
SKILL.md confines activity to a local/LAN Gaggiuino endpoint and routes all machine interaction through scripts/gaggiuino.sh. The wrapper reads/writes a per-user file (~/.openclaw/workspace/memory/gaggiuino-base-url.json) to persist a base URL and will send HTTP requests to that saved URL or to mDNS hostname gaggiuino.local. This is expected for the feature set, but it means the skill will contact whichever base URL is saved — if you set it to a remote/untrusted host it will transmit machine telemetry/commands there (the docs warn about this).
Install Mechanism
No install spec; the skill is instruction+script based and does not download external archives or add binaries. It relies on existing system tools (curl, python, ffmpeg/ffprobe). No network-based installer or URL downloads were observed.
Credentials
The skill requests no environment credentials and uses only standard runtime environment items (HOME). It creates a per-user state file under ~/.openclaw/workspace/memory to store the preferred base URL. This is proportionate, but be aware that the saved base URL can point to arbitrary HTTP(S) hosts (no strong validation), so saving an untrusted URL would cause subsequent requests to contact that host.
Persistence & Privilege
always:false and user-invocable:true. The skill only persists a small per-user config file in the skill's expected workspace and does not modify other skills or system-wide settings. It does re-exec to enforce PYTHONNOUSERSITE in renderers, which is normal for reproducible rendering.
Assessment
This skill appears to be what it says: a local Gaggiuino machine controller and shot-analysis/rendering tool that uses curl, Python, and ffmpeg locally. Before installing or using it, consider: 1) It will create and read ~/.openclaw/workspace/memory/gaggiuino-base-url.json to remember a base URL — only save a trusted LAN address; do not point it at unknown remote servers because the skill will send machine telemetry/commands to the saved URL. 2) It executes ffmpeg/ffprobe and Python scripts on your machine — review the included scripts if you want to verify they meet your security/privacy expectations. 3) No external downloads or secret environment variables are required by default. If you plan to use a remote control endpoint or share outputs externally, audit that endpoint first. If you want me to, I can point out the exact lines where the base URL is read/written and where HTTP requests are made.

Like a lobster shell, security has layers — review code before you run it.

latestvk9717gcb1mxprx6wfj74mm71ps83y583

License

MIT-0
Free to use, modify, and redistribute. No attribution required.

Runtime requirements

Binscurl, python3, mktemp, ffmpeg, ffprobe

SKILL.md

Gaggiuino Local

Gaggiuino Local is a machine-connected skill for espresso machines running the Gaggiuino mod. It supports machine control, espresso shot analysis through profile intent, troubleshooting and dial-in guidance, profile management, settings work, shot graph rendering, and synchronized overlay videos for extraction footage.

Its core question is not simply “is this cup good?” It first asks whether the shot became what its profile intended it to be. In other words, it asks:

Did this shot become the kind of coffee it was trying to be?

In Chinese:

这杯咖啡有没成为它本来想成为的样子?

Only after that does the analysis move into troubleshooting or dial-in guidance.

All machine interaction goes through scripts/gaggiuino.sh.


What this skill is for

Use this skill when the task involves one or more of these:

  • checking machine status, readiness, temperature, water level, or the active profile / 当前状态
  • analyzing the latest shot / 萃取 or a historical shot (preferred; strongest evidence)
  • rendering static or animated shot graphs, or generating synchronized overlay videos / 萃取可视化与视频叠加
  • troubleshooting or dialing in espresso taste and shot behavior
  • recommending a profile / 曲线 or profile family
  • listing or switching profiles / 曲线 on the real machine
  • helping identify what family a named profile / 曲线 belongs to
  • reading or updating Gaggiuino settings
  • interpreting shot-graph screenshots or machine screen photos (fallback; lower-confidence evidence)

What this skill is not for

  • It is not a generic coffee essay generator.
  • It is not a profile-name cookbook detached from real machine behavior.
  • It should not answer live-status questions from memory or guesswork when the API path is available.
  • It should not assume every coffee question needs machine control if the user is only asking for general dial-in reasoning.

Direct machine asks

Immediate command routing

  • machine status / readiness / temperature / online / current profile / 当前状态 / 准备好了没 / 当前温度 / 在线吗 / 当前曲线 / 现在是什么曲线
    scripts/gaggiuino.sh status
  • available profiles / what profiles are installed / 有哪些曲线 / 可用曲线 / 装了哪些曲线
    scripts/gaggiuino.sh profiles
  • switch to a named profile / use profile XXX / 切到 XXX 曲线 / 换成 XXX 曲线 / 用 XXX 曲线
    scripts/gaggiuino.sh profiles → resolve id → scripts/gaggiuino.sh select-profile <id>
  • latest shot / last shot / latest extraction / 最新一杯 / 最新萃取 / 上一杯 / 最近一杯
    scripts/gaggiuino.sh latest-shot
  • historical shot by id / shot by id / extraction by id / 按 id 查历史萃取 / 查某一杯历史记录
    scripts/gaggiuino.sh shot <id>
  • settings read/change / 读设置 / 改设置 / 查看设置 / 修改设置
    scripts/gaggiuino.sh get-settings <category> first, then scripts/gaggiuino.sh update-settings <category> <json>
  • shot graph (static/animated) / overlay video / 生成(静态/动态)萃取图 / 合成萃取视频
    scripts/render_shot_graph.py & scripts/render_shot_video_overlay.py

Connection default and fallback

  • default base URL is http://gaggiuino.local

  • gaggiuino.local is the machine's mDNS hostname

  • the saved LAN address is stored at ~/.openclaw/workspace/memory/gaggiuino-base-url.json

  • on first use, if no saved LAN address exists, try gaggiuino.local first

  • if a saved LAN address exists, try it first and fall back to gaggiuino.local on connection-layer failure

  • if both the saved address and gaggiuino.local fail, treat the saved address as possibly stale and guide the user to re-check the machine's network or update the saved address

  • if gaggiuino.local fails and no saved LAN address exists, guide the user to find the machine's real LAN IP in router settings

  • for long-term stability, suggest setting a DHCP static lease on the router

  • when the user confirms a stable LAN IP they want to keep using, save it with scripts/gaggiuino.sh set-base-url <url-or-host>

  • use scripts/gaggiuino.sh get-base-url to inspect the saved address

  • use scripts/gaggiuino.sh clear-base-url to remove it

  • these addresses are intended for trusted local/LAN endpoints; do not point them at untrusted remote servers

  • prefer retrying with a concrete LAN IP over guessing


Terminology normalization

Use these as output-normalization rules, especially when replying in Chinese coffee context. They are meant to prevent literal but unnatural translations.

General rule

  • Match the user's language.
  • In Chinese coffee context, prefer established coffee terms over literal translation.
  • Treat these as normalization hints for analysis and replies, unless the user clearly means something else.

Core term mappings

  • profile曲线
  • dial-in调磨
  • shot萃取
  • phase阶段
  • Bloom焖蒸
  • phase transition阶段切换 / 阶段过渡
  • yield出液
  • channeling通道效应
  • puck粉饼
    • Do not use the literal sports translation 冰球.
  • control mode控制模式
  • family方案
  • flow phase流速先决阶段
  • pressure phase压力先决阶段

Local alias / machine-specific interpretation

  • In this local context, 超萃 usually refers to the local HyperEx / HyperEx 2.0 profiles.
  • When users say 超萃 here, default to checking whether they mean the local HyperEx lineage first.

Phase Replay Nomenclature (Target vs Limit)

Use the terminology rules above, but for phase-transition replays and control-mode summaries apply the following stricter formatting rules.

When writing phase transition replays or summarizing control modes, strictly avoid exposing raw machine fields or machine-style shorthand such as type: "FLOW", target.end: 3, restriction: 4, stopConditions.pressureAbove: 4, or compressed tuples built from them. Translate them into human-readable descriptions centered on Targets, Limits, and exit conditions.

Critically: Match the output language strictly to the user's query language. Do not mix English and Chinese.

For type: flow:

  • The mode is the flow phase (EN) / 流速先决阶段 (CN).
  • The flow target is the target (EN) / 目标流速 (CN).
  • The pressure limit is the limit (EN) / 压力限制 (CN).
  • Format Example (EN): "Flow phase, flow target 12 ml/s, pressure limit 6 bar."
  • Format Example (CN): "流速先决阶段,目标流速 12 ml/s,压力限制 6 bar。"

For type: pressure:

  • The mode is the pressure phase (EN) / 压力先决阶段 (CN).
  • The pressure target is the target (EN) / 目标压力 (CN).
  • The flow limit is the limit (EN) / 流速限制 (CN).
  • Format Example (EN): "Pressure phase, pressure target 6 bar, flow limit 2 ml/s."
  • Format Example (CN): "压力先决阶段,目标压力 6 bar,流速限制 2 ml/s。"

Core operating rule

Always decide first whether the task is mainly about:

  1. real machine state / real shot data
  2. general dial-in reasoning
  3. graph interpretation
  4. local profile classification

Then read only the references needed for that path.

For real machine tasks, default to:

  1. fetch the actual state / shot / settings payload
  2. reconstruct what the named profile actually tried to do
  3. interpret the machine-side semantics correctly
  4. use family as an interpretation layer, not the first execution verdict
  5. only then recommend the next move

Primary routing logic

Analysis Principle: Family vs. Profile

Use family as an interpretation layer, not as the first execution verdict. In real-shot analysis, judge the intended named profile first, then use family to explain broader intent, likely expectations, and common misreads.

A shot may fit the broader family yet still fail to express the named profile. A shot may also express the named profile coherently and still be worth changing for taste reasons.

For full machine semantics, read:

For family intent, graph interpretation, and broader next-move reasoning, read:


1. Current machine state / readiness / live status

If the user asks whether the machine is ready, online, hot enough, or what profile is active:

  • run scripts/gaggiuino.sh status immediately
  • use references/analysis-protocol.md only if interpretation is needed
  • if the connection fails, apply the mDNS → LAN IP fallback rule above

2. Latest shot / historical shot analysis

If the user wants analysis of the latest shot or a specific shot:

  • run scripts/gaggiuino.sh latest-shot or scripts/gaggiuino.sh shot <id>
  • if a specific named profile is known and more than the raw phase list is needed, read references/profile-descriptions.md
  • then follow the mandatory shot-analysis order below

Mandatory shot-analysis order

For latest-shot or historical-shot analysis, do not jump straight to troubleshooting. Always complete the following order before giving recommendations:

  1. Identify the named profile and intended structure

    • read the embedded profile metadata first
    • if the named profile is known and the analysis needs more than the raw phase list, read references/profile-descriptions.md
    • identify the strongest available source for intended execution: profile.phases first, then profile description when needed
  2. Reconstruct what actually executed

    • read references/analysis-protocol.md
    • replay the control modes, targets, limits, exits, skips, and handoffs
    • keep intended structure and actual behavior separate
  3. Add family interpretation only after the execution replay

    • resolve the intended family from references/profile-mapping.md when mapped
    • use references/profile-families.md only when broader family interpretation is still needed
    • use family to explain intent and misread risk, not as the first execution verdict
    • in real-shot analysis with a known named profile, do not present family as a second conclusion; use it only to clarify intent, likely expectations, or common misreads
  4. Judge expression at the right level

    • state whether the named profile appears:
      • expressed
      • partially expressed
      • failed to express
    • if useful, also state whether the broader family still fits
    • do not give grind / ratio / pressure advice before making this judgment
  5. Classify the main problem type and next move

    • prefer phase execution and shot-condition diagnosis before profile fragility
    • distinguish the immediate trigger from any profile-level susceptibility
    • then give the smallest sensible next move

Recommended answer structure for shot analysis

When replying to latest-shot or historical-shot requests, prefer this structure:

  • Profile: <profile name>
  • Execution summary: what phases / handoffs actually ran
  • Profile expression: expressed / partially expressed / failed
  • Family intention: only when it adds value; explain the family-level intent or expected misread without turning it into a second conclusion
  • Primary issue type: phase execution / shot condition / mixed / rare profile fragility
  • Next move: 1–2 concrete actions only

Hard guardrail

Do not collapse real shot analysis into a generic coffee answer. Do not let family resemblance outrank a clearer profile-specific execution mismatch. Treat profile.name as the starting point, not the conclusion. If profile.phases clearly indicate a different known variant within the same broader family, use phase structure to refine the resolved variant. Keep intended structure and actual behavior separate: processedShot.profile.phases define the intended program structure; processedShot.datapoints show what the machine actually did over the shot. Do not use execution datapoints to replace a clearer structural signal already present in the profile phase definitions. A shot-analysis answer is incomplete unless it explicitly states whether the named profile expressed / partially expressed / failed to express before giving troubleshooting or dial-in advice. For staged named profiles, do not equate “all expected phases were entered” with “the profile was fully expressed”; judge whether key setup stages actually had enough runtime to perform their intended role.

3. Shot Visualization / 萃取可视化

The skill includes a unified rendering engine for transforming shot data into visual assets. All modes share a deterministic 2400x1080 pixel layout to ensure consistency between static and animated output. Both rendering scripts support absolute or relative paths, including user-home expansion (~) and automatic creation of missing parent directories.

Standard Output Location

All visual assets generated by the skill are captured in a defined standard directory with automatic naming:

  • Static: shot<id>_static.png
  • Animated: shot<id>_animated.mp4
  • Overlay: shot<id>_overlay_landscape.mp4 or shot<id>_overlay_portrait.mp4 ~/.openclaw/workspace/gaggiuino-output

The --out parameter is optional; if omitted, the scripts will automatically archive the file using this standard location and naming convention.

Rendering Modes

  • Static Graph (PNG): A single high-resolution image (2400x1080) for quick review.
  • Dynamic Animation (MP4): A 10fps animation showing the progression of the shot with a moving time cursor. Supports multi-process rendering for high-speed output.
  • Video Overlay (MP4): Synchronizes graph animation with a user-supplied extraction video.
    • Landscape video: Stacks the graph animation on top of the original video.
    • Portrait video: Overlays the graph animation semi-transparently at the top or bottom of the video.
    • Sync Offset / Auto Sync: If the user supplies --offset, the renderer uses that manual value. If --offset is omitted, the renderer automatically detects the earliest credible machine-start onset from video audio. When switch and pump onset are effectively fused in the recording, the event may be classified as switch_pump_merged rather than a clean isolated switch click.

Visualization CLI Reference

Graph Renderer

scripts/render_shot_graph.py

# Generate static PNG (shot<id>_static.png)
python3 render_shot_graph.py --shot-id <id> --mode png

# Generate animated MP4 (shot<id>_animated.mp4)
python3 render_shot_graph.py --shot-id <id> --mode mp4
Video Overlay Renderer

scripts/render_shot_video_overlay.py Synchronization Offset / Auto Sync

  • --offset <seconds>: Align the graph with the video using a manual value.
    • Positive (e.g., 1.4): Video started before the shot. Graph animation will wait 1.4s before starting.
    • Negative (e.g., -1.2): Shot started before the video recording.
  • If --offset is omitted, the renderer automatically detects the earliest credible machine-start onset from the video audio.
  • Auto-detected events may be reported as:
    • switch: a reasonably isolated switch onset
    • switch_pump_merged: switch and pump onset are effectively fused in the recording
    • pump: pump onset used as the best available machine-start proxy
  • --audio-sync-mode <auto|switch|pump>: choose the sync strategy.
  • --audio-debug: include detailed detection diagnostics in stderr / JSON output.

Landscape (Horizontal) Automatically uses a Vertical Stack (VSTACK) layout. The graph is placed above the video.

# Manual sync: video starts 1.4s before graph
python3 render_shot_video_overlay.py --shot-id <id> --video landscape.mp4 --offset 1.4

# Auto sync from machine-start onset
python3 render_shot_video_overlay.py --shot-id <id> --video landscape.mp4

Portrait (Vertical / Smartphone) Automatically uses a Semi-transparent Overlay. The graph floats over the video.

  • --alpha <0.1-1.0>: Adjust opacity (1.0 = solid, 0.7 is recommended).
  • --position <top/bottom>: Place the graph at the top or bottom of the frame.
# Portrait overlay with auto sync and custom alpha at the bottom
python3 render_shot_video_overlay.py --shot-id <id> --video portrait.mp4 --alpha 0.7 --position bottom

4. Taste-based dial-in and troubleshooting with no telemetry

If the user only describes taste, extraction behavior, or dialing problems:

Conceptual profile-fragility questions with no telemetry

If the user asks a conceptual causality question such as “does this mean the profile itself is flawed?” but does not provide telemetry or explicit multi-shot evidence:

  • do not jump straight to profile design as the main diagnosis
  • apply the same single-shot-first logic from references/analysis-protocol.md
  • treat profile fragility as a secondary suspicion unless the current analysis explicitly includes multiple comparable shots showing the same failure pattern under otherwise reasonable preparation
  • if needed, use references/extraction-levers.md to explain why the next move should still target shot condition, evenness, or family choice before redesigning the profile

5. Graph / screenshot / curve reading

If the user provides a graph screenshot, machine screen image, or curve description:

Mandatory graph-analysis order

  1. Assess evidence quality

    • note what is visible, missing, and how confident the read can be
  2. Do a provisional family read

    • identify the most likely family from the visible graph shape
    • keep it provisional unless the intended profile is already known
  3. Upgrade immediately if the user supplies profile context

    • if the user gives a named profile, profile description, or phase details, re-check the graph against that known structure
    • do not equate “fits the family” with “the named profile was successfully expressed”
  4. State the result at the right level

    • if only family-level evidence exists, report a family-level judgment
    • if named-profile structure is known, report both family fit and named-profile fit
  5. Keep the next move minimal

    • prefer asking for intended profile or cup result over aggressive dial-in advice from a weak image alone

Recommended answer structure for graph analysis

  • Likely family: <family> (<confidence>)
  • Evidence quality: strong / partial / weak
  • What the graph most likely shows: the 2–4 most important observations
  • What remains uncertain: missing intent / weak image / missing profile context
  • Next move: ask for intended profile or give 1 tentative adjustment

Hard guardrails

  • Do not treat a visual family inference as settled fact when the intended profile is unknown.
  • Do not treat “fits the family” as equivalent to “the named profile expressed successfully.”
  • If the user later provides stronger profile context, revise the earlier graph read instead of merely relabeling it.

6. Profile selection and family reasoning

If the user asks what profile / 曲线 to use, what a named profile / 曲线 is like, or asks to switch profiles / 曲线:

Mandatory profile-selection order

First distinguish between:

  • conceptual profile advice
  • real machine profile switching

Do not treat a profile question as permission to change the machine.

For conceptual profile advice:

For real machine switching, always follow this order:

  1. Confirm explicit switching intent

    • only switch when the user clearly wants the real machine changed
    • if the user is still comparing options, stay in advice mode
  2. Resolve the requested profile against the machine list

    • run scripts/gaggiuino.sh profiles first
    • resolve the requested name to a concrete profile id from the returned list
    • if multiple candidates match, ask before switching
  3. Send the switch request precisely

    • use scripts/gaggiuino.sh select-profile <id> only after the target id is clear
    • do not guess a profile id from memory or from a partial name alone
  4. Report switch status precisely

    • treat select-profile <id> as a sent request, not a confirmed switch, unless a follow-up read confirms it
    • if confirmation matters, read machine state or profiles again after sending the request

Hard guardrail

For real profile switching, the minimum valid sequence is:

confirm explicit switch intent → list profiles → resolve concrete id → send switch request → report status precisely

7. Settings changes

If the user wants machine settings changed:

  • always get-settings <category> first
  • then make the minimal requested change
  • then update-settings <category> <json>
  • use references/analysis-protocol.md for settings-safety rules

Mandatory settings-change order

For settings changes, first distinguish between a read request and a write request. Do not treat a settings question as permission to modify the machine.

For real settings writes, always follow this order:

  1. Read the current category first

    • run scripts/gaggiuino.sh get-settings <category> before planning the write
    • do not invent or guess the current payload
  2. Modify only the explicit delta

    • preserve every untouched field from the fetched payload
    • change only what the user clearly asked to change
    • do not rewrite the whole category speculatively
  3. Require clarity before writing

    • if the target category, field, or intended value is ambiguous, ask before posting
    • if the user is only exploring options, explain first and wait for explicit change intent
  4. Write back a complete valid payload

    • use scripts/gaggiuino.sh update-settings <category> <json> with a complete payload based on the fetched response
    • do not send a partial delta-only payload when the endpoint expects the full category object
  5. Report status precisely

    • do not claim a speculative or unperformed change was applied
    • if the write was sent, say it was sent
    • if confirmation matters, read the category again and compare the returned values

Hard guardrail

For settings writes, the minimum valid sequence is:

read current category → modify explicit delta only → write complete payload → report status precisely


Machine-specific hard rules

When interpreting real Gaggiuino data:

  • in flow phases, the flow target is the target and the pressure limit is the limit
  • in pressure phases, the pressure target is the target and the flow limit is the limit
  • do not misread healthy pressure decline in a flow-led phase as automatic channeling
  • real telemetry is stronger evidence than screenshots
  • in real-shot analysis, judge execution against the intended named profile first
  • then use the intended family to explain broader intent and avoid universal 9-bar assumptions

Language and tone

  • Reply in the same language as the user.
  • Prefer practical, specific guidance over coffee-theory monologues.
  • Use theory to explain decisions, not to overwhelm the answer.
  • When machine data is available, keep interpretations tied to actual numbers and actual shot behavior.

Host dependencies

The visualization and rendering features require these system-level tools to be installed on the host:

Public install strategy

  • Debian/Ubuntu:
    sudo apt install python3-matplotlib ffmpeg
    
  • macOS (Homebrew):
    brew install ffmpeg python-matplotlib
    

Notes

  • On this host, PYTHONNOUSERSITE=1 is automatically used by the renderers to avoid numpy 2.x ABI conflicts from user-site packages in ~/.local.

Reference map

Common references

Gaggiuino-specific references


This is an unofficial, non-commercial interoperability skill for machines running the Gaggiuino mod. It does not include or redistribute Gaggiuino source code. Any Gaggiuino-related materials remain subject to their original terms, including the project’s CC BY-NC 4.0 license where applicable.

Some reference material in this skill was adapted from https://espressoaf.com/guides and https://github.com/Zer0-bit/gaggiuino/tree/community/profiles. The Gaggiuino-specific analysis protocol in this skill is an original local framework built on top of those sources and real machine behavior.

Acknowledgement: Gaggiuino — the greatest coffee project on the planet.

Files

12 total
Select a file
Select a file to preview.

Comments

Loading comments…