Agent skill

Verify Lemon

by z80dev in z80dev/lemon

Verify lemon features against a running (or disposable) instance using the cheapest sufficient tier: DIRECT (attach/RPC + control-plane WS + bus observation, no Telegram), FAKE TELEGRAM (hermetic…

MITAuto-check: notesTesting & QA

Install Verify Lemon

skills CLI
$ npx skills add z80dev/lemon --skill verify-lemon -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install z80dev/lemon verify-lemon --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/z80dev/lemon.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/verify-lemon .claude/skills/verify-lemon && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
verify-lemon
GitHub stars
131
Token cost
~4k tokens
SKILL.md length
1,175 words
Files
1
Skills in repo
6
Repo updated
First seen
Licence
MIT

At a glance

Verify lemon features against a running (or disposable) instance using the cheapest sufficient tier: DIRECT (attach/RPC + control-plane WS + bus observation, no Telegram), FAKE TELEGRAM (hermetic…

  • Feature verification
  • SKILL.md covers Tier 1 — DIRECT (no Telegram), Tier 2 — FAKE TELEGRAM…, Tier 3 — LIVE TELEGRAM and Safety rules
  • Calls uv; needs LEMON_TELEGRAM_BOT_TOKEN and TELEGRAM_BOT_TOKEN
  • Regression repros

What it does

Verify Lemon is an agent skill from z80dev/lemon. Verify lemon features against a running (or disposable) instance using the cheapest sufficient tier: DIRECT (attach/RPC + control-plane WS + bus observation, no Telegram), FAKE TELEGRAM (hermetic transport via LemonChannels.Telegram.FakeAPI), or LIVE TELEGRAM (scripts/telegramdriver.py against the real bot). Use for feature verification, E2E checks, regression repros, and post-change validation.

Its SKILL.md is about 4k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Testing & QA, covering End-to-end testing. It works with Telegram. The repository describes itself as: BEAM-native platform for LLM agents: OTP-supervised per-run processes, pluggable engines and channels, contract-tested extension points, and a deterministic multi-agent sim arena. The licence is MIT.

When your agent uses it

  • Feature verification
  • Regression repros
  • Post-change validation

Example prompts

  • “/verify-lemon”

Requirements

  • Python 3
  • Pre-approved tools (allowed-tools): Read, Grep, Bash, Glob, Write

What it can do on your machine

Read from SKILL.md and the folder at commit 899e215. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves these tools, so the agent can use them without asking each time:

    • Read
    • Grep
    • Bash
    • Glob
    • Write

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • uv

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md. Its commands use uv, which can reach the network depending on how they are called.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names these keys or tokens, usually read from environment variables:

    • LEMON_TELEGRAM_BOT_TOKEN
    • TELEGRAM_BOT_TOKEN

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Verify Lemon loads about 4k tokens when it runs. Until then it costs about 103 tokens; SKILL.md has 1,175 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~103
When it runs · the whole SKILL.md, loaded when a task matches
~4k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check: notes

The automated check noted patterns worth knowing about, such as sudo or a known installer.

  • NotePre-approves every shell command (allowed-tools: Bash)SKILL.md
    allowed-tools: Read, Grep, Bash, Glob, Write

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from z80dev/lemon at commit 899e215, republished under its MIT licence (© z80dev). 1,175 words, ~3,961 tokens.

Download SKILL.mdSave it as .claude/skills/verify-lemon/SKILL.md (or your agent's skills folder).
name
verify-lemon
description
Verify lemon features against a running (or disposable) instance using the cheapest sufficient tier: DIRECT (attach/RPC + control-plane WS + bus observation, no Telegram), FAKE TELEGRAM (hermetic transport via LemonChannels.Telegram.FakeAPI), or LIVE TELEGRAM (scripts/telegram_driver.py against the real bot). Use for feature verification, E2E checks, regression repros, and post-change validation.
allowed-tools
Read, Grep, Bash, Glob, Write
disable-model-invocation
true
argument-hint
[feature or behavior to verify]

Verify Lemon

A runbook for verifying lemon behavior end to end. Work in three tiers and always prefer the lowest tier that can answer the question — most claims about routing, sessions, runs, delivery, and transport plumbing never need real Telegram.

TierWhat it exercisesWhen
1 DIRECTRouter, sessions, runs, bus events, control plane, delivery funnelDefault. Anything not Telegram-wire-specific
2 FAKE TELEGRAMThe real Telegram transport + outbound, hermetically (no network)Buttons, approvals, forum topics, markdown chunking, offset/poller semantics
3 LIVE TELEGRAMReal Bot API + real chat UXOnly for wire-level/UX claims the fake cannot prove

If $ARGUMENTS is provided, scope the verification session to that feature.

Tier 1 — DIRECT (no Telegram)

Attaching to a running instance

Discover the node name and cookie from the beam process args (or fall back to bin/lemon defaults: node lemon, cookie lemon_gateway_dev_cookie, control plane 4040, web 4080, sim UI 4090):

More than one beam can be running (production + a disposable instance you started, e.g. via scripts/product_smoke_local). NEVER pick one blindly — list them, check the registered names, and select the node you actually mean:

bash
epmd -names                    # every distributed node on this machine
ps -eo pid,args | grep beam.smp | grep -v grep | grep -o '\-sname [^ ]*'

Then extract the cookie from the args of that specific node's process:

bash
# -sname and -setcookie are adjacent "<flag>\n<value>" pairs in the beam args
NODE=lemon_bot   # <- the node you chose above, not just "the first beam"
ARGS=$(ps -eo args | grep beam.smp | grep -v grep | grep -- "-sname[= ]$NODE" | head -1 | tr ' ' '\n')
COOKIE=$(echo "$ARGS" | grep -A1 '^-setcookie$' | tail -1)   # NEVER echo/print this

The read-only-on-production rule below depends on this selection being right: if two nodes are up and you are about to mutate state, double-check you are attached to the disposable one (its name will look like product_smoke_<pid> or whatever --sname you passed).

Non-interactive one-shot eval on the node (the expression runs in a fresh process on the remote node, so a subscribe + receive in one expression works):

bash
elixir --sname "probe_$$" --cookie "$COOKIE" \
  --rpc-eval "$NODE@$(hostname -s)" \
  'LemonCore.RunStore.list_sessions() |> length() |> IO.inspect(label: "sessions")'

For interactive introspection use iex --sname attach_$$ --cookie "$COOKIE" --remsh "$NODE@$(hostname -s)".

Read-only by default. Against the user's production node, restrict yourself to inspection (:sys.get_state/1, store reads, Bus.subscribe). Anything that starts runs or sends messages belongs on a disposable instance.

Control-plane WebSocket (port 4040)

An unauthenticated local connect gets the operator role with all scopes (parse_role(_) -> :operator in LemonControlPlane.Auth.Authorize), so a plain WS client can drive everything. Frames are {"type":"req","id":...,"method":...,"params":{...}}; the server answers hello-ok to connect and {"type":"res","id":...} to requests. Useful methods (exact names from LemonControlPlane.Methods.Registry):

  • connect → hello-ok handshake (send {"client":{"id":...,"name":...}})
  • chat.send — params sessionKey (required), prompt, optional agentId, queueMode
  • agent — params prompt (required), session_key, model, idempotency_key; returns run_id
  • agent.wait — params runId, timeoutMs; blocks until the run completes
  • events.subscribe — params topics (allowed: all, system, cron, nodes, presence, exec_approvals, channels, goals, plus run:<id> / runId)
  • sessions.list — params limit, offset, agentId
  • logs.tail — params limit (max 1000), level

Minimal probe with python-websockets (no install needed via uv; websocat works too if present):

bash
uv run --with websockets python - <<'PY'
import asyncio, json, websockets

async def main():
    async with websockets.connect("ws://127.0.0.1:4040/ws") as ws:
        async def req(id_, method, params):
            await ws.send(json.dumps(
                {"type": "req", "id": id_, "method": method, "params": params}))

        async def recv_until(pred):
            while True:
                frame = json.loads(await ws.recv())
                if pred(frame):
                    return frame

        await req("c1", "connect", {"client": {"id": "verify", "name": "Verify"}})
        await recv_until(lambda f: f.get("type") == "hello-ok")

        await req("a1", "agent", {"prompt": "ping",
                                  "session_key": "agent:verify:main"})
        run = await recv_until(lambda f: f.get("type") == "res" and f.get("id") == "a1")
        run_id = run["payload"]["run_id"]

        await req("w1", "agent.wait", {"runId": run_id, "timeoutMs": 10000})
        done = await recv_until(lambda f: f.get("type") == "res" and f.get("id") == "w1")
        assert isinstance(done["payload"]["answer"], str), done
        print("native run ok:", run_id)

asyncio.run(main())
PY
Observing runs on the bus

From an attached node (or --rpc-eval), subscribe to LemonCore.Bus topics — "run:<run_id>" and "session:<session_key>" carry typed events (LemonCore.Event structs; catalog in docs/platform/bus-events.md):

bash
elixir --sname "probe_$$" --cookie "$COOKIE" --rpc-eval "$NODE@$(hostname -s)" '
LemonCore.Bus.subscribe("session:agent:verify:main")
receive do
  %LemonCore.Event{} = event -> IO.inspect({event.type, event.ts_ms}, label: "event")
after
  30_000 -> IO.puts("no event in 30s")
end
'
Observing outbound channel delivery (ChannelDelivery)

Every LemonChannels.Dispatcher.dispatch/1 (success and failure) now emits:

  • telemetry [:lemon, :channels, :dispatch] — measurements %{count: 1, duration: native}, metadata %{channel_id, account_id, kind, intent_id, run_id, session_key, ok}
  • a typed LemonCore.Events.ChannelDelivery broadcast as :channel_delivery on the "channels" bus topic (fields: intent_id, run_id, session_key, channel_id, account_id, peer_kind, peer_id, thread_id, kind, text_preview ≤200 chars, ok, error, duration_ms, ts_ms)
  • a control-plane WS event channel.delivery (camelCase payload), received by clients subscribed via events.subscribe with topics: ["channels"]

So "did lemon actually deliver a reply to the channel?" is answerable without touching the channel:

bash
elixir --sname "probe_$$" --cookie "$COOKIE" --rpc-eval "$NODE@$(hostname -s)" '
LemonCore.Bus.subscribe("channels")
receive do
  %LemonCore.Event{type: :channel_delivery, payload: p} ->
    IO.inspect({p.channel_id, p.kind, p.ok, p.text_preview}, label: "delivery")
after
  30_000 -> IO.puts("no delivery in 30s")
end
'
Injecting synthetic channel-shaped inbound

To exercise the router pipeline with a channel-shaped message (bypassing any transport), build a %LemonCore.InboundMessage{} (enforced keys: channel_id, account_id, peer, message) and hand it to LemonChannels.Runtime.submit_inbound/1 — on a disposable/test instance only, since this starts a real run and a real outbound delivery:

elixir
LemonChannels.Runtime.submit_inbound(%LemonCore.InboundMessage{
  channel_id: "telegram",
  account_id: "default",
  peer: %{kind: :dm, id: "310001", thread_id: nil},
  sender: %{id: "310001", username: "probe", display_name: "Probe"},
  message: %{id: "1", text: "hello from probe", timestamp: System.system_time(:second), reply_to_id: nil},
  raw: %{},
  meta: %{}
})
Deterministic agents-under-test
  • Local provider fixture — scripts/product_smoke_local boots a disposable native executor against a deterministic Responses API fixture with no live provider credentials.
  • LemonPlatformTest.FakeLLM — scripted stream function for LemonAgent loops in ExUnit: FakeLLM.script([{:tool_call, "name", %{...}}, {:text, "answer"}]) yields a conforming provider stream, letting you assert tool-call handling without a network.
Spinning a disposable instance

scripts/product_smoke_local is the reference recipe (dev boot; --release for CI-parity release boot). It is safe next to the production node: temp HOME (never the real ~/.lemon), unique --sname product_smoke_$$ + random cookie, dynamic free ports, isolated store/dotenv, kills only what it started. Run it as-is for a green/red product check, or copy its isolation levers for a custom instance:

bash
scripts/product_smoke_local            # PASS/FAIL + .lemon/proofs/product-smoke-local-latest.json
PRODUCT_SMOKE_KEEP_WORKDIR=1 scripts/product_smoke_local   # keep workdir for debugging

Port-collision env knobs (all honored by config/runtime.exs): LEMON_CONTROL_PLANE_PORT, LEMON_WEB_PORT, LEMON_SIM_UI_PORT, LEMON_GATEWAY_HEALTH_PORT=0, LEMON_ROUTER_HEALTH_PORT=0 (0 = ephemeral bind, avoids the running instance's fixed 4042), plus LEMON_STORE_PATH, LEMON_DOTENV_DIR, LEMON_GATEWAY_NODE_NAME, LEMON_GATEWAY_NODE_COOKIE.

Show full SKILL.md (464 more words)Show less

Tier 2 — FAKE TELEGRAM (hermetic transport testing)

Prefer this tier for anything Telegram-specific that does not require the real wire: inline buttons/callback queries, approval flows, forum-topic threading, markdown chunking/rendering, poller offset semantics, file transfer — all without real-TG flakiness, rate limits, or credentials.

LemonChannels.Telegram.FakeAPI (apps/lemon_channels/lib/lemon_channels/telegram/fake_api.ex) mirrors every api_mod function the real transport calls. Select it exactly like an operator would:

toml
[gateway.telegram]
bot_token = "fake-token"          # accepted, never recorded
api_mod = "LemonChannels.Telegram.FakeAPI"

or in ExUnit, pass the module straight to the transport (see apps/lemon_channels/test/lemon_channels/adapters/telegram/transport_fake_api_test.exs for the full boot + RouterBridge stub recipe):

elixir
LemonChannels.Adapters.Telegram.Transport.start_link(
  config: %{bot_token: "fake-token", api_mod: LemonChannels.Telegram.FakeAPI}
)

Drive it — fabricate inbound, await captured outbound:

elixir
# Inbound: enqueue a realistic message update (auto bot_command entity for "/...")
FakeAPI.simulate_message(4242, "/status")
FakeAPI.simulate_message(-100_320_002, "in a topic", message_thread_id: 777)
FakeAPI.simulate_callback_query(4242, "approve|once", message_id: 1000)

# Outbound: block until the transport calls the API, then inspect
{:ok, %{fun: :send_message, args: [chat_id, text, opts, parse_mode]}} =
  FakeAPI.await_send(:send_message, 10_000)

FakeAPI.sent()                      # all captured calls %{fun, args, at_ms}
FakeAPI.stub(:get_chat_member, {:ok, %{"ok" => true, "result" => %{"status" => "administrator"}}})
FakeAPI.put_file("file-1", "bytes") # get_file/2 + download_file/2 round-trip
FakeAPI.reset()                     # queue + captures + stubs + files (counters survive, safe mid-poll)

Against a test-booted live instance with the fake configured, the same driving API works over --rpc-eval (the FakeAPI GenServer is name-registered on that node; the transport lazily boots it):

bash
elixir --sname "probe_$$" --cookie "$COOKIE" --rpc-eval "$TESTNODE@$(hostname -s)" \
  'LemonChannels.Telegram.FakeAPI.simulate_message(4242, "/status") |> Map.get("update_id") |> IO.inspect()'
elixir --sname "probe_$$" --cookie "$COOKIE" --rpc-eval "$TESTNODE@$(hostname -s)" \
  'LemonChannels.Telegram.FakeAPI.await_send(:send_message, 10_000) |> inspect() |> IO.puts()'

The house smoke proves the whole loop (string-config api_mod resolution, inbound round trip, offset advance, callback answer, outbound delivery) and writes a proof artifact:

bash
MIX_ENV=test mix run scripts/live_fake_telegram_smoke.exs
# -> .lemon/proofs/fake-telegram-smoke-latest.json, exit 1 on any failed check

Tier 3 — LIVE TELEGRAM

Only when the claim is about the real wire or real chat UX (Bot API behavior, actual rendering in clients, live latency). Use scripts/telegram_driver.py — a Telethon library + CLI sharing the matrix harness's credential loading (~/.zeebot/api_keys/telegram.txt; Bot API token from LEMON_TELEGRAM_BOT_TOKEN/TELEGRAM_BOT_TOKEN env, the credentials file, or the lemon secrets store — never printed).

CLI subcommands (all take --credentials --group --bot --repo-root --json; chat commands add --chat --topic-id; waiting commands add --timeout --idle-timeout --limit):

bash
uv run scripts/telegram_driver.py topic-create "[verify] my probe" --json
uv run scripts/telegram_driver.py send-and-await "reply with exactly OK" --topic-id "$TOPIC" --json
uv run scripts/telegram_driver.py await --topic-id "$TOPIC" --after-id 1234 --json
uv run scripts/telegram_driver.py send "hello" --chat bot --json          # DM to the bot
uv run scripts/telegram_driver.py press-button --message-id 1240 "Approve once" --json
uv run scripts/telegram_driver.py topic-delete "$TOPIC" --json
uv run scripts/telegram_driver.py topic-cleanup "[verify]" --dry-run --json

Exit codes: 0 ok (await/send-and-await require ≥1 reply), 1 ok:false, 2 error (--json prints {"ok":false,"error":...}). Library use: async with TelegramDriver() as driver: with send / await_replies / send_and_await / press_button / create_topic / delete_topic / cleanup_topics (see the module docstring).

Test-group conventions:

  • Target the Lemonade Stand group (default -1003842984060, bot zeebot_lemon_bot).
  • Create temp topics with a recognizable prefix (e.g. [verify] or [adhoc]), do all probing inside them.
  • ALWAYS clean up your topics when done: topic-delete each one, or topic-cleanup "<your-prefix>" (it never touches the General topic, id 1; run --dry-run first).

Related tooling: scripts/live_telegram_matrix.py for the fixed live scenario matrix (DM/topic isolation/cancel/approval/markdown/long-output), the stress-test-lemon command for the 8-test parallel stress run, and .claude/skills/telegram-gateway-debug-loop/SKILL.md for deep debugging with gateway debug logs + remote shell.

Safety rules

  • Never print secrets. No bot tokens, api_id/api_hash, session strings, or Erlang cookies in output, code, commits, or reports. Credentials stay in ~/.zeebot/api_keys/telegram.txt and the lemon secrets store — reference paths, hold values only in shell variables/memory.
  • Never touch the user's real ~/.lemon or the production node. Do not kill lemon_bot@<host>, do not bind its ports (4040/4080/4042), do not start runs or send messages on it. Attach read-only at most; anything mutating runs on a disposable instance (scripts/product_smoke_local isolation levers).
  • Always clean up: temp forum topics (topic-cleanup), disposable instances (product_smoke_local cleans up after itself; kill only pids you started), and any transports/fakes you booted in a VM (GenServer.stop, FakeAPI.reset()).
  • Prefer lower tiers. Tier 1 for routing/session/run/delivery claims, Tier 2 for Telegram transport semantics, Tier 3 only when the real wire is the thing under test.

© z80dev, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .claude/skills/verify-lemon of z80dev/lemon.

Open the folder on GitHubat commit 899e215

Compare with similar skills

Verify Lemon next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Verify Lemon compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Verify Lemon this skillz80dev/lemon131—~4kAutomated safety check: NotesMIT
Codex CLI TaskLeoYeAI/openclaw-master-skills2.2k—~7.1kAutomated safety check: PassMIT
Better Notifybetter-notify/better-notify313—~783Automated safety check: PassMIT
SsrSAP/spartacus784—~229Automated safety check: PassApache-2.0
Tanstack Startasmyshlyaev177/test-proxy-recorder112—~2.9kAutomated safety check: NotesMIT
Acp Local Runnerrebornix/Agmente545—~804Automated safety check: PassMIT

Similar skills

  • Codex CLI Task

    LeoYeAI/openclaw-master-skills

    Launch OpenAI Codex CLI async in background with automatic delivery to Telegram/WhatsApp.

    2.2k GitHub stars~7.1k tokensUpdated 2 mo ago
    Testing & QAAuto-check passed
  • Better Notify

    better-notify/better-notify

    End-to-end typed notification infrastructure for Node.js — typed catalog of email, SMS, push, web push, WhatsApp, Slack, Discord, Telegram, and GitHub notifications with provider-agnostic transports.

    313 GitHub stars~783 tokensUpdated 1 mo ago
    Backend & APIsAuto-check passed
  • Ssr

    SAP/spartacus

    Official

    A skill your agent uses when working with Spartacus Server-Side Rendering (SSR).

    784 GitHub stars~229 tokensUpdated today
    Testing & QAAuto-check passed
  • Tanstack Start

    asmyshlyaev177/test-proxy-recorder

    Record and replay TanStack Start SSR with test-proxy-recorder.

    112 GitHub stars~2.9k tokensUpdated 4 days ago
    Testing & QAAuto-check: notes
  • Acp Local Runner

    rebornix/Agmente

    Run and debug Agmente ACP end-to-end scenarios from the repo-owned e2e/scenarios/acp specs.

    545 GitHub stars~804 tokensUpdated 4 mo ago
    Testing & QAAuto-check passed
  • Release Train Prep

    lablup/backend.ai-webui

    Post a Korean release risk digest to a Microsoft Teams thread, grouped by risk category.

    133 GitHub stars~5k tokensUpdated today
    Testing & QAAuto-check passed

More from z80dev/lemon

  • Debug and stress-test lemon gateway behavior by acting as both sides of Telegram conversations: run lemon-gateway with debug logs, then use Telethon with user credentials to send/reply messages in a…

    131 GitHub stars~744 tokensUpdated 21 days ago
    Auto-check: notes
  • Pinata

    z80dev/lemon

    Pin files and JSON to IPFS via Pinata (JWT auth + helper scripts).

    131 GitHub stars~418 tokensUpdated 21 days ago
    Auto-check passed
  • Discord Client

    z80dev/lemon

    Interact with Discord via a bot: read channels, send messages, list guilds/channels, upload files, manage threads.

    131 GitHub stars~771 tokensUpdated 21 days ago
    Auto-check: notes
  • Runtime Remsh

    z80dev/lemon

    Connect to a running Lemon or lemon-gateway BEAM node, run recompile() for hot code reload, and execute Elixir code in that live runtime via IEx remsh or rpc-eval.

    131 GitHub stars~819 tokensUpdated 21 days ago
    Auto-check passed
  • Session Logs

    z80dev/lemon

    Search and analyze your own Lemon session logs (older/parent conversations) using jq.

    131 GitHub stars~949 tokensUpdated 21 days ago
    Auto-check passed

Works with

Questions about Verify Lemon

What does Verify Lemon do?

Verify lemon features against a running (or disposable) instance using the cheapest sufficient tier: DIRECT (attach/RPC + control-plane WS + bus observation, no Telegram), FAKE TELEGRAM (hermetic…. Verify Lemon is an agent skill from z80dev/lemon.py against the real bot).

When should I use Verify Lemon?

Verify Lemon fits situations like: feature verification; regression repros; post-change validation.

How do I install Verify Lemon in Claude Code?

Run `npx skills add z80dev/lemon --skill verify-lemon -a claude-code`. Or copy the skill folder (.claude/skills/verify-lemon in z80dev/lemon) into .claude/skills/verify-lemon in your project. Claude Code loads it when a task matches its description.

How do I install Verify Lemon in Codex?

Run `npx skills add z80dev/lemon --skill verify-lemon -a codex`. Or copy the skill folder (.claude/skills/verify-lemon in z80dev/lemon) into .agents/skills/verify-lemon in your project. Codex loads it when a task matches its description.

Can I use Verify Lemon in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add z80dev/lemon --skill verify-lemon -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/verify-lemon, .gemini/skills/verify-lemon, .github/skills/verify-lemon and .opencode/skills/verify-lemon in your project.

What does Verify Lemon need to run?

Going by SKILL.md and its folder, Verify Lemon needs the command-line tools its instructions call (uv) and credentials named LEMON_TELEGRAM_BOT_TOKEN and TELEGRAM_BOT_TOKEN. Our summary lists: Python 3. Its frontmatter pre-approves these tools: Read, Grep, Bash, Glob, Write.

Does Verify Lemon access the network?

SKILL.md contains no URLs. Its commands use uv, which can reach the network depending on how they are called. This is read from the text; nothing was executed.

Is Verify Lemon safe to install?

Our automated static check of SKILL.md found notes only (pre-approves every shell command (allowed-tools: bash)), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.

What licence does Verify Lemon use?

Verify Lemon is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Verify Lemon use?

About 4k tokens (SKILL.md is roughly 16k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Verify Lemon?

Skills that share tags, products or a category with Verify Lemon: Codex CLI Task (LeoYeAI/openclaw-master-skills, 2.2k stars), Better Notify (better-notify/better-notify, 313 stars), Ssr (SAP/spartacus, 784 stars) and Tanstack Start (asmyshlyaev177/test-proxy-recorder, 112 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Verify Lemon?

z80dev (a GitHub user) maintains it in z80dev/lemon, which has 131 GitHub stars. The repository holds 6 skills in this directory. The repository was last updated on September 16, 2026.

Source: z80dev/lemon on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.