{"id":"ea76e5cb-cf62-44ae-b88d-8cd23c39b6ec","entityType":"agent","slug":"clawhub-jeminay-demo-slap","name":"Demo Slap","canonicalUrl":"https://www.xpersona.co/agent/clawhub-jeminay-demo-slap","canonicalPath":"/agent/clawhub-jeminay-demo-slap","generatedAt":"2026-10-11T07:41:55.582Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T04:13:48.246Z","emptyReason":null},"description":"Generate CS2 highlights and fragmovies from demos using the Demo-Slap API, with optional Leetify integration and Demo-Slap match history fallback to select r...","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1.2K downloads reported by the source. Last updated 10/11/2026.","installCommand":"clawhub skill install s170dx4nw2adr8scv090bb28dd84pbe2:demo-slap","sourceUrl":"https://clawhub.ai/jeminay/demo-slap","homepage":"https://clawhub.ai/jeminay/skills/demo-slap","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/jeminay/demo-slap","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/jeminay/skills/demo-slap","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":61,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"Demo Slap technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-11T04:13:48.246Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T04:13:48.246Z","emptyReason":null},"stars":null,"forks":null,"downloads":1164,"packageName":null,"latestVersion":"0.1.4","tractionLabel":"1.2K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T04:13:48.177Z","emptyReason":null},"lastUpdatedAt":"2026-10-11T04:13:48.246Z","lastCrawledAt":"2026-10-11T04:13:48.177Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-12T04:13:48.177Z","lastVerifiedAt":null,"highlights":[{"version":"0.1.4","createdAt":"2026-03-15T05:27:13.100Z","changelog":"Metadata/docs cleanup: documented optional Leetify and watchdog env inputs explicitly, clarified deployment-provided watchdog job id, and polished runtime requirements text.","fileCount":16,"zipByteSize":19765},{"version":"0.1.3","createdAt":"2026-03-15T05:24:04.354Z","changelog":"Security wording cleanup: made Leetify truly optional in metadata, removed hardcoded watchdog job id and absolute paths, and reframed watchdog guidance as deployment-specific.","fileCount":15,"zipByteSize":18296},{"version":"0.1.2","createdAt":"2026-03-15T05:19:56.272Z","changelog":"Refined public wording: clarified OpenClaw runtime assumptions, declared Leetify env/bin context, and softened watchdog/runtime guidance without changing functionality.","fileCount":15,"zipByteSize":18142},{"version":"0.1.1","createdAt":"2026-03-15T05:12:58.553Z","changelog":"ClawHub cleanup: removed runtime data files and pycache, restored runtime requirements metadata, and cleaned SKILL.md paths/docs.","fileCount":15,"zipByteSize":17922},{"version":"0.1.0","createdAt":"2026-03-15T05:09:43.263Z","changelog":"Initial public release: Demo-Slap highlights/fragmovies skill with Leetify integration and Demo-Slap match history fallback.","fileCount":15,"zipByteSize":17860},{"version":"1.0.1","createdAt":"2026-02-27T13:32:55.062Z","changelog":"Added metadata requirements (DEMOSLAP_API_KEY, ffmpeg)","fileCount":3,"zipByteSize":6461},{"version":"1.0.0","createdAt":"2026-02-27T13:14:44.912Z","changelog":"Initial release","fileCount":3,"zipByteSize":6393}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s170dx4nw2adr8scv090bb28dd84pbe2:demo-slap","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s170dx4nw2adr8scv090bb28dd84pbe2:demo-slap` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/jeminay/demo-slap before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-jeminay-demo-slap/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-jeminay-demo-slap/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-jeminay-demo-slap/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-jeminay-demo-slap/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-jeminay-demo-slap/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-jeminay-demo-slap/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-11T07:41:55.581Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-jeminay-demo-slap/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-jeminay-demo-slap/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-jeminay-demo-slap/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-jeminay-demo-slap/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T04:13:48.246Z","emptyReason":null},"readme":"Skill: Demo Slap\n\nOwner: jeminay\n\nSummary: Generate CS2 highlights and fragmovies from demos using the Demo-Slap API, with optional Leetify integration and Demo-Slap match history fallback to select r...\n\nTags: latest:0.1.4\n\nVersion history:\n\nv0.1.4 | 2026-03-15T05:27:13.100Z | user\n\nMetadata/docs cleanup: documented optional Leetify and watchdog env inputs explicitly, clarified deployment-provided watchdog job id, and polished runtime requirements text.\n\nv0.1.3 | 2026-03-15T05:24:04.354Z | user\n\nSecurity wording cleanup: made Leetify truly optional in metadata, removed hardcoded watchdog job id and absolute paths, and reframed watchdog guidance as deployment-specific.\n\nv0.1.2 | 2026-03-15T05:19:56.272Z | user\n\nRefined public wording: clarified OpenClaw runtime assumptions, declared Leetify env/bin context, and softened watchdog/runtime guidance without changing functionality.\n\nv0.1.1 | 2026-03-15T05:12:58.553Z | user\n\nClawHub cleanup: removed runtime data files and pycache, restored runtime requirements metadata, and cleaned SKILL.md paths/docs.\n\nv0.1.0 | 2026-03-15T05:09:43.263Z | user\n\nInitial public release: Demo-Slap highlights/fragmovies skill with Leetify integration and Demo-Slap match history fallback.\n\nv1.0.1 | 2026-02-27T13:32:55.062Z | user\n\nAdded metadata requirements (DEMOSLAP_API_KEY, ffmpeg)\n\nv1.0.0 | 2026-02-27T13:14:44.912Z | user\n\nInitial release\n\nArchive index:\n\nArchive v0.1.4: 16 files, 19765 bytes\n\nFiles: scripts/demo_slap_analyze.py (5475b), scripts/demo_slap_common.py (4297b), scripts/demo_slap_match_pick.py (2866b), scripts/demo_slap_matches.py (3572b), scripts/demo_slap_render.py (7103b), scripts/demo_slap_resolve.py (2566b), scripts/demo_slap_task.md (1054b), scripts/demo_slap_watchdog.sh (973b), scripts/leetify/__init__.py (18b), scripts/leetify/leetify_common.py (1466b), scripts/leetify/leetify_matches.py (2772b), scripts/leetify/leetify_resolve.py (2109b), scripts/leetify/leetify_save_id.py (433b), skill-card.md (2281b), SKILL.md (8913b), _meta.json (128b)\n\nFile v0.1.4:SKILL.md\n\n---\nname: demo-slap\ndescription: Generate CS2 highlights and fragmovies from demos using the Demo-Slap API, with optional Leetify integration and Demo-Slap match history fallback to select recent matches. Use when a user asks to record a highlight, render a clip, make a fragmovie, clip a round, or turn a CS2 demo into MP4 video.\nmetadata:\n  {\n    \"openclaw\": {\n      \"requires\": {\n        \"env\": [\"DEMOSLAP_API_KEY\"],\n        \"bins\": [\"python3\", \"openclaw\"]\n      }\n    }\n  }\n---\n\n# Demo-Slap Highlight Skill\n\nGenerate MP4 highlights and fragmovies from CS2 demos.\n\nThis skill is designed for OpenClaw environments where background jobs, local helper scripts, and chat-aware delivery are available. It uses Python 3 scripts and the `requests` package for HTTP API access.\n\nExpected runtime inputs:\n- Required: `DEMOSLAP_API_KEY`\n- Optional: `LEETIFY_API_KEY`\n- Optional deployment helper: `DEMO_SLAP_WATCHDOG_JOB_ID`\n\n## Scripts\n\nRun bundled scripts relative to the skill root, usually from `scripts/`.\n\n### Demo-Slap\n| Script | Purpose |\n|--------|---------|\n| `demo_slap_matches.py` | List recent matches from Demo-Slap `/public-api/matches` |\n| `demo_slap_resolve.py` | Try to resolve replay/demo URL from Demo-Slap match history by index; fail clearly if the API exposes only `jobId` |\n| `demo_slap_match_pick.py` | Pick a Demo-Slap match by index and return structured match info including `jobId` |\n| `demo_slap_analyze.py` | Submit a demo for analysis, poll until done, output highlights JSON |\n| `demo_slap_render.py` | Render one or more highlights, poll until done, output clip URL |\n| `demo_slap_common.py` | Shared utilities (config, API calls, state) |\n\n### Leetify\n| Script | Purpose |\n|--------|---------|\n| `leetify/leetify_matches.py` | List recent matches |\n| `leetify/leetify_resolve.py` | Resolve replay URL by username + match index |\n| `leetify/leetify_save_id.py` | Save username -> Steam64 ID mapping |\n| `leetify/leetify_common.py` | Shared Leetify utilities |\n\n### Match source selection\n- Prefer Leetify for recent match discovery when `LEETIFY_API_KEY` is available.\n- If `LEETIFY_API_KEY` is not configured but `DEMOSLAP_API_KEY` is available, use Demo-Slap match history from `/public-api/matches`.\n- Swagger: `https://api-doc.demo-slap.net/`\n- Treat Demo-Slap match history as the fallback discovery path for listing matches and selecting an existing analyzed match or replay context before analyze/render.\n\n## Runtime files\n\nUse these files as optional local runtime state during execution:\n- `data/state.json`\n- `data/highlights.json`\n- `data/history.log`\n- `data/steam_ids.json`\n- `data/config.json`\n\nThese files are runtime helpers for local operation and are not required to understand or inspect the skill package itself.\n\n`state.json` tracks the current operation:\n```json\n{\n  \"status\": \"idle|analyzing|rendering|done|error\",\n  \"job_id\": \"...\",\n  \"render_job_id\": \"...\",\n  \"chat_id\": \"telegram:182314856\",\n  \"clip_urls\": {\"highlight_id\": \"https://...\"},\n  \"progress\": \"polling 3/30\",\n  \"last_completed_op\": \"analyze|render\",\n  \"notification\": {\n    \"sent\": false,\n    \"sent_at\": null,\n    \"last_attempt_at\": null,\n    \"error\": null\n  },\n  \"updated_at\": \"ISO timestamp\"\n}\n```\n\n## Workflow\n\n### 1. Find the match\nPreferred path when `LEETIFY_API_KEY` is available:\n```bash\npython3 scripts/leetify/leetify_matches.py <USERNAME> [--limit 10]\n```\n\nFallback path when `LEETIFY_API_KEY` is missing but `DEMOSLAP_API_KEY` is available:\n```bash\npython3 scripts/demo_slap_matches.py [<USERNAME>] [--limit 10]\n```\n- uses Demo-Slap `/public-api/matches`\n- use the Demo-Slap swagger docs at `https://api-doc.demo-slap.net/` if schema details are needed\n- if `<USERNAME>` is provided and mapped, filter matches to that player's Steam ID when possible\n- after the user picks a match, run:\n```bash\npython3 scripts/demo_slap_match_pick.py [<USERNAME>] --match-index <N>\n```\n- treat the returned `jobId` as the primary handle for downstream Demo-Slap operations\n\n### 2. Resolve replay URL\nPreferred path when using Leetify:\n```bash\npython3 scripts/leetify/leetify_resolve.py <USERNAME> --match-index <N>\n```\n\nWhen using Demo-Slap fallback:\n```bash\npython3 scripts/demo_slap_match_pick.py [<USERNAME>] --match-index <N>\n```\n- use the returned `jobId` as the selected match identifier\n- if `demoUrl` is present, you may still use analyze-by-URL\n- if `demoUrl` is absent, skip URL resolution and continue by API endpoints that accept the existing analyze `jobId`\n- use `GET /public-api/analyze/{jobId}/status` and `GET /public-api/analyze/{jobId}/data` to inspect existing highlights\n- if the user wants clips and highlights already exist, render directly from that `jobId`\n\n### 3. Analyze in background\n```bash\npython3 -u scripts/demo_slap_analyze.py --url '<REPLAY_URL>' --username <USERNAME> --chat-id <CHAT_ID>\n```\n\nRun with `exec(background: true)` and keep the returned process/session id.\n\nOptional deployment-specific watchdog pattern for OpenClaw environments:\n- Use a watchdog only when background analyze/render work benefits from periodic delivery checks.\n- Reuse an existing deployment watchdog when available instead of assuming a new persistent scheduler entry is always needed.\n- If a deployment chooses to create or enable a watchdog through the built-in `cron` tool, keep it scoped to the active run and disable it again after terminal delivery.\n- A 2 minute interval is a reasonable default.\n- Use `scripts/demo_slap_watchdog.sh status|tail|job` only as a local helper for inspecting runtime state, logs, or deployment-specific job references.\n- Treat `data/state.json` and `data/highlights.json` as the source of truth during runtime.\n\nAgent workflow:\n1. Choose the match source:\n   - Leetify if `LEETIFY_API_KEY` exists\n   - Demo-Slap `/public-api/matches` if `LEETIFY_API_KEY` is missing and `DEMOSLAP_API_KEY` exists\n2. If using Leetify, resolve the replay URL and run analyze\n3. If using Demo-Slap fallback, pick a match and inspect the returned `jobId`\n4. If the selected Demo-Slap match already has analyze data, continue by `jobId` instead of forcing analyze-by-URL\n5. Use or enable a deployment watchdog only when long-running analyze/render work benefits from it\n6. Launch analyze or render and save the returned process/session id when applicable\n7. Let the watchdog deliver the result when a deployment uses one\n8. Disable the watchdog again after terminal delivery\n\n### 4. Render in background\n```bash\n# Single highlight\npython3 -u scripts/demo_slap_render.py <JOB_ID> <HIGHLIGHT_ID> --chat-id <CHAT_ID>\n\n# Fragmovie\npython3 -u scripts/demo_slap_render.py <JOB_ID> <ID1> <ID2> ... --fragmovie --chat-id <CHAT_ID>\n```\n\nRun with `exec(background: true)` and keep the returned process/session id.\n\nOptional deployment-specific watchdog pattern for OpenClaw environments:\n- Use a watchdog only when background analyze/render work benefits from periodic delivery checks.\n- Reuse an existing deployment watchdog when available instead of assuming a new persistent scheduler entry is always needed.\n- If a deployment chooses to create or enable a watchdog through the built-in `cron` tool, keep it scoped to the active run and disable it again after terminal delivery.\n- A 2 minute interval is a reasonable default.\n- Use `scripts/demo_slap_watchdog.sh status|tail|job` only as a local helper for inspecting runtime state, logs, or deployment-specific job references.\n- Treat `data/state.json` and `data/highlights.json` as the source of truth during runtime.\n\nAgent workflow:\n1. Enable or reuse a deployment watchdog only when needed for the active run\n2. Launch render and save the returned process/session id\n3. Poll process output for the `Estimated finish:` line and tell the user the ETA if present\n4. Let the watchdog deliver the result when one is in use\n5. Disable the watchdog again after terminal delivery\n\n**Critical:** set `<CHAT_ID>` from inbound metadata of the originating request. Treat hardcoded chat identifiers as local examples only, not as a reusable default.\n\n### 5. Check status\nRead `data/state.json`.\n\n## Setup\n\n### Map username to Steam ID\n```bash\npython3 scripts/leetify/leetify_save_id.py <USERNAME> <STEAM_64_ID>\n```\n\n### Configure API keys\nPrefer environment variables:\n- `DEMOSLAP_API_KEY` - required\n- `LEETIFY_API_KEY` - optional, only for Leetify-backed match discovery\n- `DEMO_SLAP_WATCHDOG_JOB_ID` - optional deployment-specific helper for watchdog inspection scripts\n\nSource selection rules:\n- If `LEETIFY_API_KEY` exists, use Leetify for match discovery.\n- If `LEETIFY_API_KEY` is absent but `DEMOSLAP_API_KEY` exists, use Demo-Slap `/public-api/matches` for match discovery.\n- `DEMOSLAP_API_KEY` is always required for analyze/render.\n\nOptional local fallback for controlled self-hosted setups: put them in `data/config.json`.\n\n## Support\n\nFor access and support, please join our Discord community: https://discord.gg/8nfh26W9wQ\n\nFile v0.1.4:_meta.json\n\n{\n  \"ownerId\": \"kn73589k2rv646tm107cp6d90s81g7xy\",\n  \"slug\": \"demo-slap\",\n  \"version\": \"0.1.4\",\n  \"publishedAt\": 1773552433100\n}\n\nFile v0.1.4:scripts/demo_slap_task.md\n\n# demo-slap task workflow\n\nRecommended OpenClaw runtime pattern:\n\n- do not manage the watchdog through shell cron commands\n- prefer OpenClaw's built-in cron tool when a deployment chooses to enable or disable a watchdog for a live run\n- treat watchdog configuration and any job id as deployment-specific, not globally hardcoded\n- when used, `DEMO_SLAP_WATCHDOG_JOB_ID` should be supplied by the deployment rather than embedded in the skill\n- use the shell helper only for local inspection of state/log/job references:\n\n```bash\nscripts/demo_slap_watchdog.sh status\nscripts/demo_slap_watchdog.sh tail\nscripts/demo_slap_watchdog.sh job\n```\n\nSuggested runtime workflow for assistants:\n1. Before analyze/render -> `cron.update(jobId=<watchdog>, enabled=true)` when a deployment watchdog is being used\n2. Start analyze/render\n3. Let the watchdog inspect state on a reasonable interval such as every 2 minutes\n4. After successful delivery or terminal error -> `cron.update(jobId=<watchdog>, enabled=false)` when the deployment watchdog was enabled for that run\n\nFile v0.1.4:skill-card.md\n\n## Description:\n\nGenerate CS2 highlights and fragmovies from demos using the Demo-Slap API, with optional Leetify integration and Demo-Slap match history fallback for recent match selection.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[jeminay](https://clawhub.ai/user/jeminay)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nExternal users and developers use this skill in OpenClaw environments to select CS2 matches, analyze demos, render highlight clips or fragmovies, and deliver MP4 clip URLs.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Sensitive API keys or runtime data may be kept in local configuration or data files.\n\nMitigation: Prefer environment-injected API keys, restrict access to the data directory, and avoid storing secrets in data/config.json.\n\nRisk: Untrusted job, chat, and clip data can be published into OpenClaw system events.\n\nMitigation: Use typed events or validated and redacted fields before enabling automatic delivery actions.\n\nRisk: Background watchdog jobs can continue beyond the intended render or analysis run if left enabled.\n\nMitigation: Avoid watchdog jobs when possible; when needed, scope them to the active run and disable them after terminal delivery or error.\n\n## Reference(s):\n\n- [Demo Slap on ClawHub](https://clawhub.ai/jeminay/skills/demo-slap)\n- [Demo-Slap API Swagger](https://api-doc.demo-slap.net/)\n- [Demo-Slap API](https://api.demo-slap.net)\n- [Leetify Public API](https://api-public.cs-prod.leetify.com)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, shell commands, configuration, JSON, files]\n\n**Output Format:** [Markdown guidance with inline shell commands, JSON script output, runtime state files, and MP4 clip URLs]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Requires DEMOSLAP_API_KEY; can use LEETIFY_API_KEY for match discovery and OpenClaw for background notification workflows.]\n\n## Skill Version(s):\n\n0.1.4 (source: server release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v0.1.3: 15 files, 18296 bytes\n\nFiles: scripts/demo_slap_analyze.py (5475b), scripts/demo_slap_common.py (4297b), scripts/demo_slap_match_pick.py (2866b), scripts/demo_slap_matches.py (3572b), scripts/demo_slap_render.py (7103b), scripts/demo_slap_resolve.py (2566b), scripts/demo_slap_task.md (942b), scripts/demo_slap_watchdog.sh (942b), scripts/leetify/__init__.py (18b), scripts/leetify/leetify_common.py (1466b), scripts/leetify/leetify_matches.py (2772b), scripts/leetify/leetify_resolve.py (2109b), scripts/leetify/leetify_save_id.py (433b), SKILL.md (8605b), _meta.json (128b)\n\nFile v0.1.3:SKILL.md\n\n---\nname: demo-slap\ndescription: Generate CS2 highlights and fragmovies from demos using the Demo-Slap API, with optional Leetify integration and Demo-Slap match history fallback to select recent matches. Use when a user asks to record a highlight, render a clip, make a fragmovie, clip a round, or turn a CS2 demo into MP4 video.\nmetadata:\n  {\n    \"openclaw\": {\n      \"requires\": {\n        \"env\": [\"DEMOSLAP_API_KEY\"],\n        \"bins\": [\"python3\", \"openclaw\"]\n      }\n    }\n  }\n---\n\n# Demo-Slap Highlight Skill\n\nGenerate MP4 highlights and fragmovies from CS2 demos.\n\nThis skill is designed for OpenClaw environments where background jobs, local helper scripts, and chat-aware delivery are available. It uses Python 3 scripts and the `requests` package for HTTP API access.\n\n## Scripts\n\nRun bundled scripts relative to the skill root, usually from `scripts/`.\n\n### Demo-Slap\n| Script | Purpose |\n|--------|---------|\n| `demo_slap_matches.py` | List recent matches from Demo-Slap `/public-api/matches` |\n| `demo_slap_resolve.py` | Try to resolve replay/demo URL from Demo-Slap match history by index; fail clearly if the API exposes only `jobId` |\n| `demo_slap_match_pick.py` | Pick a Demo-Slap match by index and return structured match info including `jobId` |\n| `demo_slap_analyze.py` | Submit a demo for analysis, poll until done, output highlights JSON |\n| `demo_slap_render.py` | Render one or more highlights, poll until done, output clip URL |\n| `demo_slap_common.py` | Shared utilities (config, API calls, state) |\n\n### Leetify\n| Script | Purpose |\n|--------|---------|\n| `leetify/leetify_matches.py` | List recent matches |\n| `leetify/leetify_resolve.py` | Resolve replay URL by username + match index |\n| `leetify/leetify_save_id.py` | Save username -> Steam64 ID mapping |\n| `leetify/leetify_common.py` | Shared Leetify utilities |\n\n### Match source selection\n- Prefer Leetify for recent match discovery when `LEETIFY_API_KEY` is available.\n- If `LEETIFY_API_KEY` is not configured but `DEMOSLAP_API_KEY` is available, use Demo-Slap match history from `/public-api/matches`.\n- Swagger: `https://api-doc.demo-slap.net/`\n- Treat Demo-Slap match history as the fallback discovery path for listing matches and selecting an existing analyzed match or replay context before analyze/render.\n\n## Runtime files\n\nUse these files as optional local runtime state during execution:\n- `data/state.json`\n- `data/highlights.json`\n- `data/history.log`\n- `data/steam_ids.json`\n- `data/config.json`\n\nThese files are runtime helpers for local operation and are not required to understand or inspect the skill package itself.\n\n`state.json` tracks the current operation:\n```json\n{\n  \"status\": \"idle|analyzing|rendering|done|error\",\n  \"job_id\": \"...\",\n  \"render_job_id\": \"...\",\n  \"chat_id\": \"telegram:182314856\",\n  \"clip_urls\": {\"highlight_id\": \"https://...\"},\n  \"progress\": \"polling 3/30\",\n  \"last_completed_op\": \"analyze|render\",\n  \"notification\": {\n    \"sent\": false,\n    \"sent_at\": null,\n    \"last_attempt_at\": null,\n    \"error\": null\n  },\n  \"updated_at\": \"ISO timestamp\"\n}\n```\n\n## Workflow\n\n### 1. Find the match\nPreferred path when `LEETIFY_API_KEY` is available:\n```bash\npython3 scripts/leetify/leetify_matches.py <USERNAME> [--limit 10]\n```\n\nFallback path when `LEETIFY_API_KEY` is missing but `DEMOSLAP_API_KEY` is available:\n```bash\npython3 scripts/demo_slap_matches.py [<USERNAME>] [--limit 10]\n```\n- uses Demo-Slap `/public-api/matches`\n- use the Demo-Slap swagger docs at `https://api-doc.demo-slap.net/` if schema details are needed\n- if `<USERNAME>` is provided and mapped, filter matches to that player's Steam ID when possible\n- after the user picks a match, run:\n```bash\npython3 scripts/demo_slap_match_pick.py [<USERNAME>] --match-index <N>\n```\n- treat the returned `jobId` as the primary handle for downstream Demo-Slap operations\n\n### 2. Resolve replay URL\nPreferred path when using Leetify:\n```bash\npython3 scripts/leetify/leetify_resolve.py <USERNAME> --match-index <N>\n```\n\nWhen using Demo-Slap fallback:\n```bash\npython3 scripts/demo_slap_match_pick.py [<USERNAME>] --match-index <N>\n```\n- use the returned `jobId` as the selected match identifier\n- if `demoUrl` is present, you may still use analyze-by-URL\n- if `demoUrl` is absent, skip URL resolution and continue by API endpoints that accept the existing analyze `jobId`\n- use `GET /public-api/analyze/{jobId}/status` and `GET /public-api/analyze/{jobId}/data` to inspect existing highlights\n- if the user wants clips and highlights already exist, render directly from that `jobId`\n\n### 3. Analyze in background\n```bash\npython3 -u scripts/demo_slap_analyze.py --url '<REPLAY_URL>' --username <USERNAME> --chat-id <CHAT_ID>\n```\n\nRun with `exec(background: true)` and keep the returned process/session id.\n\nOptional deployment-specific watchdog pattern for OpenClaw environments:\n- Use a watchdog only when background analyze/render work benefits from periodic delivery checks.\n- Reuse an existing deployment watchdog when available instead of assuming a new persistent scheduler entry is always needed.\n- If a deployment chooses to create or enable a watchdog through the built-in `cron` tool, keep it scoped to the active run and disable it again after terminal delivery.\n- A 2 minute interval is a reasonable default.\n- Use `scripts/demo_slap_watchdog.sh status|tail|job` only as a local helper for inspecting runtime state, logs, or deployment-specific job references.\n- Treat `data/state.json` and `data/highlights.json` as the source of truth during runtime.\n\nAgent workflow:\n1. Choose the match source:\n   - Leetify if `LEETIFY_API_KEY` exists\n   - Demo-Slap `/public-api/matches` if `LEETIFY_API_KEY` is missing and `DEMOSLAP_API_KEY` exists\n2. If using Leetify, resolve the replay URL and run analyze\n3. If using Demo-Slap fallback, pick a match and inspect the returned `jobId`\n4. If the selected Demo-Slap match already has analyze data, continue by `jobId` instead of forcing analyze-by-URL\n5. Use or enable a deployment watchdog only when long-running analyze/render work benefits from it\n6. Launch analyze or render and save the returned process/session id when applicable\n7. Let the watchdog deliver the result when a deployment uses one\n8. Disable the watchdog again after terminal delivery\n\n### 4. Render in background\n```bash\n# Single highlight\npython3 -u scripts/demo_slap_render.py <JOB_ID> <HIGHLIGHT_ID> --chat-id <CHAT_ID>\n\n# Fragmovie\npython3 -u scripts/demo_slap_render.py <JOB_ID> <ID1> <ID2> ... --fragmovie --chat-id <CHAT_ID>\n```\n\nRun with `exec(background: true)` and keep the returned process/session id.\n\nOptional deployment-specific watchdog pattern for OpenClaw environments:\n- Use a watchdog only when background analyze/render work benefits from periodic delivery checks.\n- Reuse an existing deployment watchdog when available instead of assuming a new persistent scheduler entry is always needed.\n- If a deployment chooses to create or enable a watchdog through the built-in `cron` tool, keep it scoped to the active run and disable it again after terminal delivery.\n- A 2 minute interval is a reasonable default.\n- Use `scripts/demo_slap_watchdog.sh status|tail|job` only as a local helper for inspecting runtime state, logs, or deployment-specific job references.\n- Treat `data/state.json` and `data/highlights.json` as the source of truth during runtime.\n\nAgent workflow:\n1. Enable or reuse a deployment watchdog only when needed for the active run\n2. Launch render and save the returned process/session id\n3. Poll process output for the `Estimated finish:` line and tell the user the ETA if present\n4. Let the watchdog deliver the result when one is in use\n5. Disable the watchdog again after terminal delivery\n\n**Critical:** set `<CHAT_ID>` from inbound metadata of the originating request. Treat hardcoded chat identifiers as local examples only, not as a reusable default.\n\n### 5. Check status\nRead `data/state.json`.\n\n## Setup\n\n### Map username to Steam ID\n```bash\npython3 scripts/leetify/leetify_save_id.py <USERNAME> <STEAM_64_ID>\n```\n\n### Configure API keys\nPrefer environment variables:\n- `DEMOSLAP_API_KEY`\n- `LEETIFY_API_KEY`\n\nSource selection rules:\n- If `LEETIFY_API_KEY` exists, use Leetify for match discovery.\n- If `LEETIFY_API_KEY` is absent but `DEMOSLAP_API_KEY` exists, use Demo-Slap `/public-api/matches` for match discovery.\n- `DEMOSLAP_API_KEY` is always required for analyze/render.\n\nOptional local fallback for controlled self-hosted setups: put them in `data/config.json`.\n\n## Support\n\nFor access and support, please join our Discord community: https://discord.gg/8nfh26W9wQ\n\nFile v0.1.3:_meta.json\n\n{\n  \"ownerId\": \"kn73589k2rv646tm107cp6d90s81g7xy\",\n  \"slug\": \"demo-slap\",\n  \"version\": \"0.1.3\",\n  \"publishedAt\": 1773552244354\n}\n\nFile v0.1.3:scripts/demo_slap_task.md\n\n# demo-slap task workflow\n\nRecommended OpenClaw runtime pattern:\n\n- do not manage the watchdog through shell cron commands\n- prefer OpenClaw's built-in cron tool when a deployment chooses to enable or disable a watchdog for a live run\n- treat watchdog configuration and any job id as deployment-specific, not globally hardcoded\n- use the shell helper only for local inspection of state/log/job references:\n\n```bash\nscripts/demo_slap_watchdog.sh status\nscripts/demo_slap_watchdog.sh tail\nscripts/demo_slap_watchdog.sh job\n```\n\nSuggested runtime workflow for assistants:\n1. Before analyze/render -> `cron.update(jobId=<watchdog>, enabled=true)` when a deployment watchdog is being used\n2. Start analyze/render\n3. Let the watchdog inspect state on a reasonable interval such as every 2 minutes\n4. After successful delivery or terminal error -> `cron.update(jobId=<watchdog>, enabled=false)` when the deployment watchdog was enabled for that run\n\nArchive v0.1.2: 15 files, 18142 bytes\n\nFiles: scripts/demo_slap_analyze.py (5475b), scripts/demo_slap_common.py (4297b), scripts/demo_slap_match_pick.py (2866b), scripts/demo_slap_matches.py (3572b), scripts/demo_slap_render.py (7103b), scripts/demo_slap_resolve.py (2566b), scripts/demo_slap_task.md (764b), scripts/demo_slap_watchdog.sh (787b), scripts/leetify/__init__.py (18b), scripts/leetify/leetify_common.py (1466b), scripts/leetify/leetify_matches.py (2772b), scripts/leetify/leetify_resolve.py (2109b), scripts/leetify/leetify_save_id.py (433b), SKILL.md (8433b), _meta.json (128b)\n\nFile v0.1.2:SKILL.md\n\n---\nname: demo-slap\ndescription: Generate CS2 highlights and fragmovies from demos using the Demo-Slap API, with optional Leetify integration and Demo-Slap match history fallback to select recent matches. Use when a user asks to record a highlight, render a clip, make a fragmovie, clip a round, or turn a CS2 demo into MP4 video.\nmetadata:\n  {\n    \"openclaw\": {\n      \"requires\": {\n        \"env\": [\"DEMOSLAP_API_KEY\", \"LEETIFY_API_KEY\"],\n        \"bins\": [\"python3\", \"openclaw\"]\n      }\n    }\n  }\n---\n\n# Demo-Slap Highlight Skill\n\nGenerate MP4 highlights and fragmovies from CS2 demos.\n\nThis skill is designed for OpenClaw environments where background jobs, local helper scripts, and chat-aware delivery are available. It uses Python 3 scripts and the `requests` package for HTTP API access.\n\n## Scripts\n\nRun bundled scripts relative to the skill root, usually from `scripts/`.\n\n### Demo-Slap\n| Script | Purpose |\n|--------|---------|\n| `demo_slap_matches.py` | List recent matches from Demo-Slap `/public-api/matches` |\n| `demo_slap_resolve.py` | Try to resolve replay/demo URL from Demo-Slap match history by index; fail clearly if the API exposes only `jobId` |\n| `demo_slap_match_pick.py` | Pick a Demo-Slap match by index and return structured match info including `jobId` |\n| `demo_slap_analyze.py` | Submit a demo for analysis, poll until done, output highlights JSON |\n| `demo_slap_render.py` | Render one or more highlights, poll until done, output clip URL |\n| `demo_slap_common.py` | Shared utilities (config, API calls, state) |\n\n### Leetify\n| Script | Purpose |\n|--------|---------|\n| `leetify/leetify_matches.py` | List recent matches |\n| `leetify/leetify_resolve.py` | Resolve replay URL by username + match index |\n| `leetify/leetify_save_id.py` | Save username -> Steam64 ID mapping |\n| `leetify/leetify_common.py` | Shared Leetify utilities |\n\n### Match source selection\n- Prefer Leetify for recent match discovery when `LEETIFY_API_KEY` is available.\n- If `LEETIFY_API_KEY` is not configured but `DEMOSLAP_API_KEY` is available, use Demo-Slap match history from `/public-api/matches`.\n- Swagger: `https://api-doc.demo-slap.net/`\n- Treat Demo-Slap match history as the fallback discovery path for listing matches and selecting an existing analyzed match or replay context before analyze/render.\n\n## Runtime files\n\nUse these files as optional local runtime state during execution:\n- `data/state.json`\n- `data/highlights.json`\n- `data/history.log`\n- `data/steam_ids.json`\n- `data/config.json`\n\nThese files are runtime helpers for local operation and are not required to understand or inspect the skill package itself.\n\n`state.json` tracks the current operation:\n```json\n{\n  \"status\": \"idle|analyzing|rendering|done|error\",\n  \"job_id\": \"...\",\n  \"render_job_id\": \"...\",\n  \"chat_id\": \"telegram:182314856\",\n  \"clip_urls\": {\"highlight_id\": \"https://...\"},\n  \"progress\": \"polling 3/30\",\n  \"last_completed_op\": \"analyze|render\",\n  \"notification\": {\n    \"sent\": false,\n    \"sent_at\": null,\n    \"last_attempt_at\": null,\n    \"error\": null\n  },\n  \"updated_at\": \"ISO timestamp\"\n}\n```\n\n## Workflow\n\n### 1. Find the match\nPreferred path when `LEETIFY_API_KEY` is available:\n```bash\npython3 scripts/leetify/leetify_matches.py <USERNAME> [--limit 10]\n```\n\nFallback path when `LEETIFY_API_KEY` is missing but `DEMOSLAP_API_KEY` is available:\n```bash\npython3 scripts/demo_slap_matches.py [<USERNAME>] [--limit 10]\n```\n- uses Demo-Slap `/public-api/matches`\n- use the Demo-Slap swagger docs at `https://api-doc.demo-slap.net/` if schema details are needed\n- if `<USERNAME>` is provided and mapped, filter matches to that player's Steam ID when possible\n- after the user picks a match, run:\n```bash\npython3 scripts/demo_slap_match_pick.py [<USERNAME>] --match-index <N>\n```\n- treat the returned `jobId` as the primary handle for downstream Demo-Slap operations\n\n### 2. Resolve replay URL\nPreferred path when using Leetify:\n```bash\npython3 scripts/leetify/leetify_resolve.py <USERNAME> --match-index <N>\n```\n\nWhen using Demo-Slap fallback:\n```bash\npython3 scripts/demo_slap_match_pick.py [<USERNAME>] --match-index <N>\n```\n- use the returned `jobId` as the selected match identifier\n- if `demoUrl` is present, you may still use analyze-by-URL\n- if `demoUrl` is absent, skip URL resolution and continue by API endpoints that accept the existing analyze `jobId`\n- use `GET /public-api/analyze/{jobId}/status` and `GET /public-api/analyze/{jobId}/data` to inspect existing highlights\n- if the user wants clips and highlights already exist, render directly from that `jobId`\n\n### 3. Analyze in background\n```bash\npython3 -u scripts/demo_slap_analyze.py --url '<REPLAY_URL>' --username <USERNAME> --chat-id <CHAT_ID>\n```\n\nRun with `exec(background: true)` and keep the returned process/session id.\n\nOptional watchdog orchestration pattern for OpenClaw deployments:\n- Keep the watchdog disabled when idle.\n- Before starting analyze, check whether a suitable watchdog cron job already exists.\n- If it does not exist, create one with the built-in `cron` tool.\n- If it exists, enable it with the built-in `cron` tool for the active run.\n- A 2 minute interval is a reasonable default.\n- After the watchdog successfully sends a result or error and `state.json` is terminal (`done` or `error`), disable the watchdog again.\n- Use `scripts/demo_slap_watchdog.sh status|tail|job` only as a local helper for inspecting state/log/job references.\n- Treat `data/state.json` and `data/highlights.json` as the source of truth during runtime.\n\nAgent workflow:\n1. Choose the match source:\n   - Leetify if `LEETIFY_API_KEY` exists\n   - Demo-Slap `/public-api/matches` if `LEETIFY_API_KEY` is missing and `DEMOSLAP_API_KEY` exists\n2. If using Leetify, resolve the replay URL and run analyze\n3. If using Demo-Slap fallback, pick a match and inspect the returned `jobId`\n4. If the selected Demo-Slap match already has analyze data, continue by `jobId` instead of forcing analyze-by-URL\n5. Enable the watchdog cron job only for long-running analyze/render work\n6. Launch analyze or render and save the returned process/session id when applicable\n7. Let the watchdog deliver the result\n8. Disable the watchdog after terminal delivery\n\n### 4. Render in background\n```bash\n# Single highlight\npython3 -u scripts/demo_slap_render.py <JOB_ID> <HIGHLIGHT_ID> --chat-id <CHAT_ID>\n\n# Fragmovie\npython3 -u scripts/demo_slap_render.py <JOB_ID> <ID1> <ID2> ... --fragmovie --chat-id <CHAT_ID>\n```\n\nRun with `exec(background: true)` and keep the returned process/session id.\n\nOptional watchdog orchestration pattern for OpenClaw deployments:\n- Keep the watchdog disabled when idle.\n- Before starting render, check whether a suitable watchdog cron job already exists.\n- If it does not exist, create one with the built-in `cron` tool.\n- If it exists, enable it with the built-in `cron` tool for the active run.\n- A 2 minute interval is a reasonable default.\n- After the watchdog successfully sends a result or error and `state.json` is terminal (`done` or `error`), disable the watchdog again.\n- Use `scripts/demo_slap_watchdog.sh status|tail|job` only as a local helper for inspecting state/log/job references.\n- Treat `data/state.json` and `data/highlights.json` as the source of truth during runtime.\n\nAgent workflow:\n1. Enable the watchdog cron job\n2. Launch render and save the returned process/session id\n3. Poll process output for the `Estimated finish:` line and tell the user the ETA if present\n4. Let the watchdog deliver the result\n5. Disable the watchdog after terminal delivery\n\n**Critical:** set `<CHAT_ID>` from inbound metadata of the originating request. Treat hardcoded chat identifiers as local examples only, not as a reusable default.\n\n### 5. Check status\nRead `data/state.json`.\n\n## Setup\n\n### Map username to Steam ID\n```bash\npython3 scripts/leetify/leetify_save_id.py <USERNAME> <STEAM_64_ID>\n```\n\n### Configure API keys\nPrefer environment variables:\n- `DEMOSLAP_API_KEY`\n- `LEETIFY_API_KEY`\n\nSource selection rules:\n- If `LEETIFY_API_KEY` exists, use Leetify for match discovery.\n- If `LEETIFY_API_KEY` is absent but `DEMOSLAP_API_KEY` exists, use Demo-Slap `/public-api/matches` for match discovery.\n- `DEMOSLAP_API_KEY` is always required for analyze/render.\n\nOptional local fallback for controlled self-hosted setups: put them in `data/config.json`.\n\n## Support\n\nFor access and support, please join our Discord community: https://discord.gg/8nfh26W9wQ\n\nFile v0.1.2:_meta.json\n\n{\n  \"ownerId\": \"kn73589k2rv646tm107cp6d90s81g7xy\",\n  \"slug\": \"demo-slap\",\n  \"version\": \"0.1.2\",\n  \"publishedAt\": 1773551996272\n}\n\nFile v0.1.2:scripts/demo_slap_task.md\n\n# demo-slap task workflow\n\nRecommended OpenClaw runtime pattern:\n\n- do not manage the watchdog through shell cron commands\n- prefer OpenClaw's built-in cron tool when enabling or disabling a watchdog for a live run\n- use the shell helper only for local inspection of state/log/job references:\n\n```bash\nscripts/demo_slap_watchdog.sh status\nscripts/demo_slap_watchdog.sh tail\nscripts/demo_slap_watchdog.sh job\n```\n\nSuggested runtime workflow for assistants:\n1. Before analyze/render -> `cron.update(jobId=<watchdog>, enabled=true)` when a watchdog is being used\n2. Start analyze/render\n3. Let the watchdog inspect state on a reasonable interval such as every 2 minutes\n4. After successful delivery or terminal error -> `cron.update(jobId=<watchdog>, enabled=false)`\n\nArchive v0.1.1: 15 files, 17922 bytes\n\nFiles: scripts/demo_slap_analyze.py (5475b), scripts/demo_slap_common.py (4297b), scripts/demo_slap_match_pick.py (2866b), scripts/demo_slap_matches.py (3572b), scripts/demo_slap_render.py (7103b), scripts/demo_slap_resolve.py (2566b), scripts/demo_slap_task.md (1006b), scripts/demo_slap_watchdog.sh (754b), scripts/leetify/__init__.py (18b), scripts/leetify/leetify_common.py (1466b), scripts/leetify/leetify_matches.py (2772b), scripts/leetify/leetify_resolve.py (2109b), scripts/leetify/leetify_save_id.py (433b), SKILL.md (7599b), _meta.json (128b)\n\nFile v0.1.1:SKILL.md\n\n---\nname: demo-slap\ndescription: Generate CS2 highlights and fragmovies from demos using the Demo-Slap API, with optional Leetify integration and Demo-Slap match history fallback to select recent matches. Use when a user asks to record a highlight, render a clip, make a fragmovie, clip a round, or turn a CS2 demo into MP4 video.\nmetadata:\n  {\n    \"openclaw\": {\n      \"requires\": {\n        \"env\": [\"DEMOSLAP_API_KEY\"],\n        \"bins\": [\"python3\"]\n      }\n    }\n  }\n---\n\n# Demo-Slap Highlight Skill\n\nGenerate MP4 highlights and fragmovies from CS2 demos.\n\n## Scripts\n\nRun bundled scripts relative to the skill root, usually from `scripts/`.\n\n### Demo-Slap\n| Script | Purpose |\n|--------|---------|\n| `demo_slap_matches.py` | List recent matches from Demo-Slap `/public-api/matches` |\n| `demo_slap_resolve.py` | Try to resolve replay/demo URL from Demo-Slap match history by index; fail clearly if the API exposes only `jobId` |\n| `demo_slap_match_pick.py` | Pick a Demo-Slap match by index and return structured match info including `jobId` |\n| `demo_slap_analyze.py` | Submit a demo for analysis, poll until done, output highlights JSON |\n| `demo_slap_render.py` | Render one or more highlights, poll until done, output clip URL |\n| `demo_slap_common.py` | Shared utilities (config, API calls, state) |\n\n### Leetify\n| Script | Purpose |\n|--------|---------|\n| `leetify/leetify_matches.py` | List recent matches |\n| `leetify/leetify_resolve.py` | Resolve replay URL by username + match index |\n| `leetify/leetify_save_id.py` | Save username -> Steam64 ID mapping |\n| `leetify/leetify_common.py` | Shared Leetify utilities |\n\n### Match source selection\n- Prefer Leetify for recent match discovery when `LEETIFY_API_KEY` is available.\n- If `LEETIFY_API_KEY` is missing but `DEMOSLAP_API_KEY` is available, use Demo-Slap match history from `/public-api/matches`.\n- Swagger: `https://api-doc.demo-slap.net/`\n- Use Demo-Slap match history only as the fallback source for listing matches and picking a replay before analyze.\n\n## Runtime files\n\nUse these files as local state only:\n- `data/state.json`\n- `data/highlights.json`\n- `data/history.log`\n- `data/steam_ids.json`\n- `data/config.json`\n\n`state.json` tracks the current operation:\n```json\n{\n  \"status\": \"idle|analyzing|rendering|done|error\",\n  \"job_id\": \"...\",\n  \"render_job_id\": \"...\",\n  \"chat_id\": \"telegram:182314856\",\n  \"clip_urls\": {\"highlight_id\": \"https://...\"},\n  \"progress\": \"polling 3/30\",\n  \"last_completed_op\": \"analyze|render\",\n  \"notification\": {\n    \"sent\": false,\n    \"sent_at\": null,\n    \"last_attempt_at\": null,\n    \"error\": null\n  },\n  \"updated_at\": \"ISO timestamp\"\n}\n```\n\n## Workflow\n\n### 1. Find the match\nPreferred path when `LEETIFY_API_KEY` is available:\n```bash\npython3 scripts/leetify/leetify_matches.py <USERNAME> [--limit 10]\n```\n\nFallback path when `LEETIFY_API_KEY` is missing but `DEMOSLAP_API_KEY` is available:\n```bash\npython3 scripts/demo_slap_matches.py [<USERNAME>] [--limit 10]\n```\n- uses Demo-Slap `/public-api/matches`\n- use the Demo-Slap swagger docs at `https://api-doc.demo-slap.net/` if schema details are needed\n- if `<USERNAME>` is provided and mapped, filter matches to that player's Steam ID when possible\n- after the user picks a match, run:\n```bash\npython3 scripts/demo_slap_match_pick.py [<USERNAME>] --match-index <N>\n```\n- treat the returned `jobId` as the primary handle for downstream Demo-Slap operations\n\n### 2. Resolve replay URL\nPreferred path when using Leetify:\n```bash\npython3 scripts/leetify/leetify_resolve.py <USERNAME> --match-index <N>\n```\n\nWhen using Demo-Slap fallback:\n```bash\npython3 scripts/demo_slap_match_pick.py [<USERNAME>] --match-index <N>\n```\n- use the returned `jobId` as the selected match identifier\n- if `demoUrl` is present, you may still use analyze-by-URL\n- if `demoUrl` is absent, skip URL resolution and continue by API endpoints that accept the existing analyze `jobId`\n- use `GET /public-api/analyze/{jobId}/status` and `GET /public-api/analyze/{jobId}/data` to inspect existing highlights\n- if the user wants clips and highlights already exist, render directly from that `jobId`\n\n### 3. Analyze in background\n```bash\npython3 -u scripts/demo_slap_analyze.py --url '<REPLAY_URL>' --username <USERNAME> --chat-id <CHAT_ID>\n```\n\nRun with `exec(background: true)` and keep the returned process/session id.\n\nWatchdog rules:\n- Keep the cron watchdog disabled by default.\n- Before starting analyze, check whether the watchdog cron job already exists.\n- If it does not exist, create it with the built-in `cron` tool.\n- If it exists, enable it with the built-in `cron` tool.\n- Use a 2 minute interval.\n- After the watchdog successfully sends a result or error and `state.json` is terminal (`done` or `error`), disable the watchdog again.\n- Use `scripts/demo_slap_watchdog.sh status|tail|job` only for local inspection.\n- Treat `data/state.json` and `data/highlights.json` as the source of truth.\n\nAgent workflow:\n1. Choose the match source:\n   - Leetify if `LEETIFY_API_KEY` exists\n   - Demo-Slap `/public-api/matches` if `LEETIFY_API_KEY` is missing and `DEMOSLAP_API_KEY` exists\n2. If using Leetify, resolve the replay URL and run analyze\n3. If using Demo-Slap fallback, pick a match and inspect the returned `jobId`\n4. If the selected Demo-Slap match already has analyze data, continue by `jobId` instead of forcing analyze-by-URL\n5. Enable the watchdog cron job only for long-running analyze/render work\n6. Launch analyze or render and save the returned process/session id when applicable\n7. Let the watchdog deliver the result\n8. Disable the watchdog after terminal delivery\n\n### 4. Render in background\n```bash\n# Single highlight\npython3 -u scripts/demo_slap_render.py <JOB_ID> <HIGHLIGHT_ID> --chat-id <CHAT_ID>\n\n# Fragmovie\npython3 -u scripts/demo_slap_render.py <JOB_ID> <ID1> <ID2> ... --fragmovie --chat-id <CHAT_ID>\n```\n\nRun with `exec(background: true)` and keep the returned process/session id.\n\nWatchdog rules:\n- Keep the cron watchdog disabled by default.\n- Before starting render, check whether the watchdog cron job already exists.\n- If it does not exist, create it with the built-in `cron` tool.\n- If it exists, enable it with the built-in `cron` tool.\n- Use a 2 minute interval.\n- After the watchdog successfully sends a result or error and `state.json` is terminal (`done` or `error`), disable the watchdog again.\n- Use `scripts/demo_slap_watchdog.sh status|tail|job` only for local inspection.\n- Treat `data/state.json` and `data/highlights.json` as the source of truth.\n\nAgent workflow:\n1. Enable the watchdog cron job\n2. Launch render and save the returned process/session id\n3. Poll process output for the `Estimated finish:` line and tell the user the ETA if present\n4. Let the watchdog deliver the result\n5. Disable the watchdog after terminal delivery\n\n**Critical:** set `<CHAT_ID>` from inbound metadata of the originating request. Never hardcode it.\n\n### 5. Check status\nRead `data/state.json`.\n\n## Setup\n\n### Map username to Steam ID\n```bash\npython3 scripts/leetify/leetify_save_id.py <USERNAME> <STEAM_64_ID>\n```\n\n### Configure API keys\nPrefer environment variables:\n- `DEMOSLAP_API_KEY`\n- `LEETIFY_API_KEY`\n\nSource selection rules:\n- If `LEETIFY_API_KEY` exists, use Leetify for match discovery.\n- If `LEETIFY_API_KEY` is absent but `DEMOSLAP_API_KEY` exists, use Demo-Slap `/public-api/matches` for match discovery.\n- `DEMOSLAP_API_KEY` is always required for analyze/render.\n\nOptional local fallback: put them in `data/config.json`.\n\n## Support\n\nFor access and support, please join our Discord community: https://discord.gg/8nfh26W9wQ\n\nFile v0.1.1:_meta.json\n\n{\n  \"ownerId\": \"kn73589k2rv646tm107cp6d90s81g7xy\",\n  \"slug\": \"demo-slap\",\n  \"version\": \"0.1.1\",\n  \"publishedAt\": 1773551578553\n}\n\nFile v0.1.1:scripts/demo_slap_task.md\n\n# demo-slap task workflow\n\nНадёжный режим работы:\n\n- watchdog cron НЕ управляется через shell CLI\n- watchdog cron включает/выключает сам ассистент через встроенный cron tool\n- shell shortcut используется только для локальной диагностики файлов:\n\n```bash\n/root/.openclaw/workspace/skills/demo-slap/scripts/demo_slap_watchdog.sh status\n/root/.openclaw/workspace/skills/demo-slap/scripts/demo_slap_watchdog.sh tail\n/root/.openclaw/workspace/skills/demo-slap/scripts/demo_slap_watchdog.sh job\n```\n\nОбязательный runtime workflow для ассистента:\n1. Перед analyze/render -> `cron.update(jobId=<watchdog>, enabled=true)`\n2. Запуск analyze/render\n3. Watchdog проверяет state каждые 2 минуты\n4. После успешной отправки результата или ошибки -> `cron.update(jobId=<watchdog>, enabled=false)`\n\nArchive v0.1.0: 15 files, 17860 bytes\n\nFiles: scripts/demo_slap_analyze.py (5475b), scripts/demo_slap_common.py (4297b), scripts/demo_slap_match_pick.py (2866b), scripts/demo_slap_matches.py (3572b), scripts/demo_slap_render.py (7103b), scripts/demo_slap_resolve.py (2566b), scripts/demo_slap_task.md (1006b), scripts/demo_slap_watchdog.sh (754b), scripts/leetify/__init__.py (18b), scripts/leetify/leetify_common.py (1466b), scripts/leetify/leetify_matches.py (2772b), scripts/leetify/leetify_resolve.py (2109b), scripts/leetify/leetify_save_id.py (433b), SKILL.md (7483b), _meta.json (128b)\n\nFile v0.1.0:SKILL.md\n\n---\nname: demo-slap\ndescription: Generate CS2 highlights and fragmovies from demos using the Demo-Slap API, with optional Leetify integration and Demo-Slap match history fallback to resolve demo URLs from a player's recent matches. Use when a user asks to record a highlight, render a clip, make a fragmovie, clip a round, or turn a CS2 demo into MP4 video.\n---\n\n# Demo-Slap Highlight Skill\n\nGenerate MP4 highlights and fragmovies from CS2 demos.\n\n## Scripts\n\nBase path: `/root/.openclaw/workspace/skills/demo-slap/scripts/`\n\n### Demo-Slap\n| Script | Purpose |\n|--------|---------|\n| `demo_slap_matches.py` | List recent matches from Demo-Slap `/public-api/matches` |\n| `demo_slap_resolve.py` | Try to resolve replay/demo URL from Demo-Slap match history by index; fail clearly if the API exposes only `jobId` |\n| `demo_slap_match_pick.py` | Pick a Demo-Slap match by index and return structured match info including `jobId` |\n| `demo_slap_analyze.py` | Submit a demo for analysis, poll until done, output highlights JSON |\n| `demo_slap_render.py` | Render one or more highlights, poll until done, output clip URL |\n| `demo_slap_common.py` | Shared utilities (config, API calls, state) |\n\n### Leetify\n| Script | Purpose |\n|--------|---------|\n| `leetify/leetify_matches.py` | List recent matches |\n| `leetify/leetify_resolve.py` | Resolve replay URL by username + match index |\n| `leetify/leetify_save_id.py` | Save username -> Steam64 ID mapping |\n| `leetify/leetify_common.py` | Shared Leetify utilities |\n\n### Match source selection\n- Prefer Leetify for recent match discovery when `LEETIFY_API_KEY` is available.\n- If `LEETIFY_API_KEY` is missing but `DEMOSLAP_API_KEY` is available, use Demo-Slap match history from `/public-api/matches`.\n- Swagger: `https://api-doc.demo-slap.net/`\n- Use Demo-Slap match history only as the fallback source for listing matches and picking a replay before analyze.\n\n## Runtime files\n\nUse these files as local state only:\n- `data/state.json`\n- `data/highlights.json`\n- `data/history.log`\n- `data/steam_ids.json`\n- `data/config.json`\n\n`state.json` tracks the current operation:\n```json\n{\n  \"status\": \"idle|analyzing|rendering|done|error\",\n  \"job_id\": \"...\",\n  \"render_job_id\": \"...\",\n  \"chat_id\": \"telegram:182314856\",\n  \"clip_urls\": {\"highlight_id\": \"https://...\"},\n  \"progress\": \"polling 3/30\",\n  \"last_completed_op\": \"analyze|render\",\n  \"notification\": {\n    \"sent\": false,\n    \"sent_at\": null,\n    \"last_attempt_at\": null,\n    \"error\": null\n  },\n  \"updated_at\": \"ISO timestamp\"\n}\n```\n\n## Workflow\n\n### 1. Find the match\nPreferred path when `LEETIFY_API_KEY` is available:\n```bash\npython3 scripts/leetify/leetify_matches.py <USERNAME> [--limit 10]\n```\n\nFallback path when `LEETIFY_API_KEY` is missing but `DEMOSLAP_API_KEY` is available:\n```bash\npython3 scripts/demo_slap_matches.py [<USERNAME>] [--limit 10]\n```\n- uses Demo-Slap `/public-api/matches`\n- use the Demo-Slap swagger docs at `https://api-doc.demo-slap.net/` if schema details are needed\n- if `<USERNAME>` is provided and mapped, filter matches to that player's Steam ID when possible\n- after the user picks a match, run:\n```bash\npython3 scripts/demo_slap_match_pick.py [<USERNAME>] --match-index <N>\n```\n- treat the returned `jobId` as the primary handle for downstream Demo-Slap operations\n\n### 2. Resolve replay URL\nPreferred path when using Leetify:\n```bash\npython3 scripts/leetify/leetify_resolve.py <USERNAME> --match-index <N>\n```\n\nWhen using Demo-Slap fallback:\n```bash\npython3 scripts/demo_slap_match_pick.py [<USERNAME>] --match-index <N>\n```\n- use the returned `jobId` as the selected match identifier\n- if `demoUrl` is present, you may still use analyze-by-URL\n- if `demoUrl` is absent, skip URL resolution and continue by API endpoints that accept the existing analyze `jobId`\n- use `GET /public-api/analyze/{jobId}/status` and `GET /public-api/analyze/{jobId}/data` to inspect existing highlights\n- if the user wants clips and highlights already exist, render directly from that `jobId`\n\n### 3. Analyze in background\n```bash\npython3 -u scripts/demo_slap_analyze.py --url '<REPLAY_URL>' --username <USERNAME> --chat-id <CHAT_ID>\n```\n\nRun with `exec(background: true)` and keep the returned process/session id.\n\nWatchdog rules:\n- Keep the cron watchdog disabled by default.\n- Before starting analyze, check whether the watchdog cron job already exists.\n- If it does not exist, create it with the built-in `cron` tool.\n- If it exists, enable it with the built-in `cron` tool.\n- Use a 2 minute interval.\n- After the watchdog successfully sends a result or error and `state.json` is terminal (`done` or `error`), disable the watchdog again.\n- Use `scripts/demo_slap_watchdog.sh status|tail|job` only for local inspection.\n- Treat `data/state.json` and `data/highlights.json` as the source of truth.\n\nAgent workflow:\n1. Choose the match source:\n   - Leetify if `LEETIFY_API_KEY` exists\n   - Demo-Slap `/public-api/matches` if `LEETIFY_API_KEY` is missing and `DEMOSLAP_API_KEY` exists\n2. If using Leetify, resolve the replay URL and run analyze\n3. If using Demo-Slap fallback, pick a match and inspect the returned `jobId`\n4. If the selected Demo-Slap match already has analyze data, continue by `jobId` instead of forcing analyze-by-URL\n5. Enable the watchdog cron job only for long-running analyze/render work\n6. Launch analyze or render and save the returned process/session id when applicable\n7. Let the watchdog deliver the result\n8. Disable the watchdog after terminal delivery\n\n### 4. Render in background\n```bash\n# Single highlight\npython3 -u scripts/demo_slap_render.py <JOB_ID> <HIGHLIGHT_ID> --chat-id <CHAT_ID>\n\n# Fragmovie\npython3 -u scripts/demo_slap_render.py <JOB_ID> <ID1> <ID2> ... --fragmovie --chat-id <CHAT_ID>\n```\n\nRun with `exec(background: true)` and keep the returned process/session id.\n\nWatchdog rules:\n- Keep the cron watchdog disabled by default.\n- Before starting render, check whether the watchdog cron job already exists.\n- If it does not exist, create it with the built-in `cron` tool.\n- If it exists, enable it with the built-in `cron` tool.\n- Use a 2 minute interval.\n- After the watchdog successfully sends a result or error and `state.json` is terminal (`done` or `error`), disable the watchdog again.\n- Use `scripts/demo_slap_watchdog.sh status|tail|job` only for local inspection.\n- Treat `data/state.json` and `data/highlights.json` as the source of truth.\n\nAgent workflow:\n1. Enable the watchdog cron job\n2. Launch render and save the returned process/session id\n3. Poll process output for the `Estimated finish:` line and tell the user the ETA if present\n4. Let the watchdog deliver the result\n5. Disable the watchdog after terminal delivery\n\n**Critical:** set `<CHAT_ID>` from inbound metadata of the originating request. Never hardcode it.\n\n### 5. Check status\nRead `data/state.json`.\n\n## Setup\n\n### Map username to Steam ID\n```bash\npython3 scripts/leetify/leetify_save_id.py <USERNAME> <STEAM_64_ID>\n```\n\n### Configure API keys\nPrefer environment variables:\n- `DEMOSLAP_API_KEY`\n- `LEETIFY_API_KEY`\n\nSource selection rules:\n- If `LEETIFY_API_KEY` exists, use Leetify for match discovery.\n- If `LEETIFY_API_KEY` is absent but `DEMOSLAP_API_KEY` exists, use Demo-Slap `/public-api/matches` for match discovery.\n- `DEMOSLAP_API_KEY` is always required for analyze/render.\n\nOptional local fallback: put them in `data/config.json`.\n\n## Support\n\nFor access and support, please join our Discord community: https://discord.gg/8nfh26W9wQ\n\nFile v0.1.0:_meta.json\n\n{\n  \"ownerId\": \"kn73589k2rv646tm107cp6d90s81g7xy\",\n  \"slug\": \"demo-slap\",\n  \"version\": \"0.1.0\",\n  \"publishedAt\": 1773551383263\n}\n\nFile v0.1.0:scripts/demo_slap_task.md\n\n# demo-slap task workflow\n\nНадёжный режим работы:\n\n- watchdog cron НЕ управляется через shell CLI\n- watchdog cron включает/выключает сам ассистент через встроенный cron tool\n- shell shortcut используется только для локальной диагностики файлов:\n\n```bash\n/root/.openclaw/workspace/skills/demo-slap/scripts/demo_slap_watchdog.sh status\n/root/.openclaw/workspace/skills/demo-slap/scripts/demo_slap_watchdog.sh tail\n/root/.openclaw/workspace/skills/demo-slap/scripts/demo_slap_watchdog.sh job\n```\n\nОбязательный runtime workflow для ассистента:\n1. Перед analyze/render -> `cron.update(jobId=<watchdog>, enabled=true)`\n2. Запуск analyze/render\n3. Watchdog проверяет state каждые 2 минуты\n4. После успешной отправки результата или ошибки -> `cron.update(jobId=<watchdog>, enabled=false)`\n\nArchive v1.0.1: 3 files, 6461 bytes\n\nFiles: scripts/demo_slap_cli.py (13408b), SKILL.md (4894b), _meta.json (128b)\n\nFile v1.0.1:SKILL.md\n\n---\nname: demo-slap\ndescription: Generate CS2 highlights and fragmovies from demos using the Demo-Slap API. Includes optional Leetify integration for auto-fetching demo URLs. Use when a user asks to \"record a highlight\", \"make a fragmovie\", \"clip that round\", etc.\nmetadata:\n  {\n    \"openclaw\": {\n      \"requires\": {\n        \"env\": [\"DEMOSLAP_API_KEY\"],\n        \"bins\": [\"ffmpeg\", \"python3\"]\n      }\n    }\n  }\n---\n\n# Demo-Slap Highlight Skill\n\nGenerate beautiful MP4 highlights and fragmovies straight from CS2 demos.\n\n## 🔗 APIs & Prerequisites\n- **Demo-Slap API:** [https://api-doc.demo-slap.net/](https://api-doc.demo-slap.net/)\n- **Leetify API (Optional but recommended):** [https://api-public-docs.cs-prod.leetify.com/](https://api-public-docs.cs-prod.leetify.com/)\n\n**Using Leetify:** \nLeetify integration is optional but highly recommended to automatically fetch demo URLs from recent matches. \n- **API Key:** Free to get at [leetify.com/app/developer](https://leetify.com/app/developer).\n- **Steam64 ID:** Users can find their 17-digit Steam64 ID using sites like [steamid.io](https://steamid.io/) or by checking their Steam profile URL.\n\n## 🛠 Identity & Setup\n\n### 1. Set API Keys (One-time setup)\nYou need to save the API keys to `data/config.json`. You can do this via the CLI:\n```bash\npython3 scripts/demo_slap_cli.py set-key demoslap <DEMOSLAP_API_KEY>\npython3 scripts/demo_slap_cli.py set-key leetify <LEETIFY_API_KEY>\n```\n*Note: The keys can also be provided via `DEMOSLAP_API_KEY` and `LEETIFY_API_KEY` environment variables.*\n\n### 2. Map User to Steam ID\nTo map a user's chat username (Telegram, Discord, Slack, etc.) or nickname to their Steam64 ID (required for Leetify match fetching and filtering their specific highlights):\n\n```bash\npython3 scripts/demo_slap_cli.py save-id <USERNAME> <STEAM_64_ID>\n```\n*If a user asks for their highlights but their Steam ID is unknown, explain how to find it (e.g., via steamid.io), then run this command.*\n\n## 📋 Step 1: Find the Match (Optional)\n\nIf the user wants a highlight from a recent match and the Leetify API key is available, you can list their recent matches:\n\n```bash\npython3 scripts/demo_slap_cli.py matches <USERNAME>\n```\n*This lists their recent matches (index 0 is the most recent). Note the index they want.*\n\nIf the Leetify API key is NOT available or the user wants to use a specific match not tracked, **ask them to provide a direct download link (.dem.gz or similar) to the demo.**\n\n## 🔍 Step 2: Analyze the Demo (Async)\n\n**CRITICAL: DO NOT BLOCK THE MAIN SESSION.** Analysis on Demo-Slap servers takes 2-4 minutes. You MUST use `sessions_spawn` to run this step asynchronously. When using relative paths, ensure your `cwd` points to this skill's folder or run the command relative to it.\n\n**Subagent Prompt Template:**\n```text\nTask: Analyze a demo for highlights.\n1. Run the analysis command:\n   # If using Leetify match index (e.g. index 0):\n   exec(command=\"python3 -u scripts/demo_slap_cli.py analyze --username <USERNAME> --match-index <N>\")\n   \n   # OR if using a direct URL:\n   exec(command=\"python3 -u scripts/demo_slap_cli.py analyze --url '<URL>' --username <USERNAME>\")\n\n2. Loop `process(action=\"poll\", sessionId=\"...\", timeout=30000)` until the script finishes.\n3. Extract the printed table of highlights (with JobID and Highlight IDs).\n4. Send the table to the user in their channel using the `message` tool (`action=\"send\"`). Ask them: \"Which Highlight ID(s) do you want to render?\"\n5. Reply NO_REPLY.\n```\n\n## 🎥 Step 3: Render Highlight or Fragmovie (Async)\n\nOnce the user replies with the Highlight ID(s) they want, render the final video.\n**CRITICAL: DO NOT BLOCK THE MAIN SESSION.** Rendering and downloading the MP4 takes 2-5 minutes. You MUST use `sessions_spawn` to run this step asynchronously.\n\n**Subagent Prompt Template:**\n```text\nTask: Render a CS2 clip.\n1. Run the render command:\n   # For a SINGLE highlight:\n   exec(command=\"python3 -u scripts/demo_slap_cli.py render <JOB_ID> <HIGHLIGHT_ID>\")\n   \n   # For a FRAGMOVIE (multiple highlights stitched together):\n   exec(command=\"python3 -u scripts/demo_slap_cli.py render-fragmovie <JOB_ID> <ID_1> <ID_2> ...\")\n\n2. Loop `process(action=\"poll\", sessionId=\"...\", timeout=30000)` until the script finishes and prints the downloaded file path (e.g., `/tmp/render_...mp4`).\n3. Check the file size using `du -m <file_path>`.\n4. If the file is > 48MB (Telegram limit), compress it:\n   `ffmpeg -i <file_path> -c:v libx264 -crf 28 -preset fast -c:a aac -b:a 128k /tmp/compressed_clip.mp4`\n   Then use the compressed file path for the next step.\n5. Send the video to the user using the `message` tool (`action=\"send\"`, `media=\"<final_file_path>\"`).\n   ⚠️ CRITICAL: Set `timeoutMs: 120000` (2 minutes) on the `message` tool call because uploading large videos takes time!\n6. Remove the MP4 files from `/tmp/`.\n7. Reply NO_REPLY.\n```\n\nFile v1.0.1:_meta.json\n\n{\n  \"ownerId\": \"kn73589k2rv646tm107cp6d90s81g7xy\",\n  \"slug\": \"demo-slap\",\n  \"version\": \"1.0.1\",\n  \"publishedAt\": 1772199175062\n}\n\nArchive v1.0.0: 3 files, 6393 bytes\n\nFiles: scripts/demo_slap_cli.py (13408b), SKILL.md (4749b), _meta.json (128b)\n\nFile v1.0.0:SKILL.md\n\n---\nname: demo-slap\ndescription: Generate CS2 highlights and fragmovies from demos using the Demo-Slap API. Includes optional Leetify integration for auto-fetching demo URLs. Use when a user asks to \"record a highlight\", \"make a fragmovie\", \"clip that round\", etc.\n---\n\n# Demo-Slap Highlight Skill\n\nGenerate beautiful MP4 highlights and fragmovies straight from CS2 demos.\n\n## 🔗 APIs & Prerequisites\n- **Demo-Slap API:** [https://api-doc.demo-slap.net/](https://api-doc.demo-slap.net/)\n- **Leetify API (Optional but recommended):** [https://api-public-docs.cs-prod.leetify.com/](https://api-public-docs.cs-prod.leetify.com/)\n\n**Using Leetify:** \nLeetify integration is optional but highly recommended to automatically fetch demo URLs from recent matches. \n- **API Key:** Free to get at [leetify.com/app/developer](https://leetify.com/app/developer).\n- **Steam64 ID:** Users can find their 17-digit Steam64 ID using sites like [steamid.io](https://steamid.io/) or by checking their Steam profile URL.\n\n## 🛠 Identity & Setup\n\n### 1. Set API Keys (One-time setup)\nYou need to save the API keys to `data/config.json`. You can do this via the CLI:\n```bash\npython3 scripts/demo_slap_cli.py set-key demoslap <DEMOSLAP_API_KEY>\npython3 scripts/demo_slap_cli.py set-key leetify <LEETIFY_API_KEY>\n```\n*Note: The keys can also be provided via `DEMOSLAP_API_KEY` and `LEETIFY_API_KEY` environment variables.*\n\n### 2. Map User to Steam ID\nTo map a user's chat username (Telegram, Discord, Slack, etc.) or nickname to their Steam64 ID (required for Leetify match fetching and filtering their specific highlights):\n\n```bash\npython3 scripts/demo_slap_cli.py save-id <USERNAME> <STEAM_64_ID>\n```\n*If a user asks for their highlights but their Steam ID is unknown, explain how to find it (e.g., via steamid.io), then run this command.*\n\n## 📋 Step 1: Find the Match (Optional)\n\nIf the user wants a highlight from a recent match and the Leetify API key is available, you can list their recent matches:\n\n```bash\npython3 scripts/demo_slap_cli.py matches <USERNAME>\n```\n*This lists their recent matches (index 0 is the most recent). Note the index they want.*\n\nIf the Leetify API key is NOT available or the user wants to use a specific match not tracked, **ask them to provide a direct download link (.dem.gz or similar) to the demo.**\n\n## 🔍 Step 2: Analyze the Demo (Async)\n\n**CRITICAL: DO NOT BLOCK THE MAIN SESSION.** Analysis on Demo-Slap servers takes 2-4 minutes. You MUST use `sessions_spawn` to run this step asynchronously. When using relative paths, ensure your `cwd` points to this skill's folder or run the command relative to it.\n\n**Subagent Prompt Template:**\n```text\nTask: Analyze a demo for highlights.\n1. Run the analysis command:\n   # If using Leetify match index (e.g. index 0):\n   exec(command=\"python3 -u scripts/demo_slap_cli.py analyze --username <USERNAME> --match-index <N>\")\n   \n   # OR if using a direct URL:\n   exec(command=\"python3 -u scripts/demo_slap_cli.py analyze --url '<URL>' --username <USERNAME>\")\n\n2. Loop `process(action=\"poll\", sessionId=\"...\", timeout=30000)` until the script finishes.\n3. Extract the printed table of highlights (with JobID and Highlight IDs).\n4. Send the table to the user in their channel using the `message` tool (`action=\"send\"`). Ask them: \"Which Highlight ID(s) do you want to render?\"\n5. Reply NO_REPLY.\n```\n\n## 🎥 Step 3: Render Highlight or Fragmovie (Async)\n\nOnce the user replies with the Highlight ID(s) they want, render the final video.\n**CRITICAL: DO NOT BLOCK THE MAIN SESSION.** Rendering and downloading the MP4 takes 2-5 minutes. You MUST use `sessions_spawn` to run this step asynchronously.\n\n**Subagent Prompt Template:**\n```text\nTask: Render a CS2 clip.\n1. Run the render command:\n   # For a SINGLE highlight:\n   exec(command=\"python3 -u scripts/demo_slap_cli.py render <JOB_ID> <HIGHLIGHT_ID>\")\n   \n   # For a FRAGMOVIE (multiple highlights stitched together):\n   exec(command=\"python3 -u scripts/demo_slap_cli.py render-fragmovie <JOB_ID> <ID_1> <ID_2> ...\")\n\n2. Loop `process(action=\"poll\", sessionId=\"...\", timeout=30000)` until the script finishes and prints the downloaded file path (e.g., `/tmp/render_...mp4`).\n3. Check the file size using `du -m <file_path>`.\n4. If the file is > 48MB (Telegram limit), compress it:\n   `ffmpeg -i <file_path> -c:v libx264 -crf 28 -preset fast -c:a aac -b:a 128k /tmp/compressed_clip.mp4`\n   Then use the compressed file path for the next step.\n5. Send the video to the user using the `message` tool (`action=\"send\"`, `media=\"<final_file_path>\"`).\n   ⚠️ CRITICAL: Set `timeoutMs: 120000` (2 minutes) on the `message` tool call because uploading large videos takes time!\n6. Remove the MP4 files from `/tmp/`.\n7. Reply NO_REPLY.\n```\n\nFile v1.0.0:_meta.json\n\n{\n  \"ownerId\": \"kn73589k2rv646tm107cp6d90s81g7xy\",\n  \"slug\": \"demo-slap\",\n  \"version\": \"1.0.0\",\n  \"publishedAt\": 1772198084912\n}","readmeExcerpt":"Skill: Demo Slap Owner: jeminay Summary: Generate CS2 highlights and fragmovies from demos using the Demo-Slap API, with optional Leetify integration and Demo-Slap match history fallback to select r... Tags: latest:0.1.4 Version history: v0.1.4 | 2026-03-15T05:27:13.100Z | user Metadata/docs cleanup: documented optional Leetify and watchdog env inputs explicitly, clarified deployment-provided watchdog job id, and pol","codeSnippets":[],"executableExamples":[{"language":"json","snippet":"{\n  \"status\": \"idle|analyzing|rendering|done|error\",\n  \"job_id\": \"...\",\n  \"render_job_id\": \"...\",\n  \"chat_id\": \"telegram:182314856\",\n  \"clip_urls\": {\"highlight_id\": \"https://...\"},\n  \"progress\": \"polling 3/30\",\n  \"last_completed_op\": \"analyze|render\",\n  \"notification\": {\n    \"sent\": false,\n    \"sent_at\": null,\n    \"last_attempt_at\": null,\n    \"error\": null\n  },\n  \"updated_at\": \"ISO timestamp\"\n}"},{"language":"bash","snippet":"python3 scripts/leetify/leetify_matches.py <USERNAME> [--limit 10]"},{"language":"bash","snippet":"python3 scripts/demo_slap_matches.py [<USERNAME>] [--limit 10]"},{"language":"bash","snippet":"python3 scripts/demo_slap_match_pick.py [<USERNAME>] --match-index <N>"},{"language":"bash","snippet":"python3 scripts/leetify/leetify_resolve.py <USERNAME> --match-index <N>"},{"language":"bash","snippet":"python3 scripts/demo_slap_match_pick.py [<USERNAME>] --match-index <N>"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: demo-slap\ndescription: Generate CS2 highlights and fragmovies from demos using the Demo-Slap API, with optional Leetify integration and Demo-Slap match history fallback to select recent matches. Use when a user asks to record a highlight, render a clip, make a fragmovie, clip a round, or turn a CS2 demo into MP4 video.\nmetadata:\n  {\n    \"openclaw\": {\n      \"requires\": {\n        \"env\": [\"DEMOSLAP_API_KEY\"],\n        \"bins\": [\"python3\", \"openclaw\"]\n      }\n    }\n  }\n---\n\n# Demo-Slap Highlight Skill\n\nGenerate MP4 highlights and fragmovies from CS2 demos.\n\nThis skill is designed for OpenClaw environments where background jobs, local helper scripts, and chat-aware delivery are available. It uses Python 3 scripts and the `requests` package for HTTP API access.\n\nExpected runtime inputs:\n- Required: `DEMOSLAP_API_KEY`\n- Optional: `LEETIFY_API_KEY`\n- Optional deployment helper: `DEMO_SLAP_WATCHDOG_JOB_ID`\n\n## Scripts\n\nRun bundled scripts relative to the skill root, usually from `scripts/`.\n\n### Demo-Slap\n| Script | Purpose |\n|--------|---------|\n| `demo_slap_matches.py` | List recent matches from Demo-Slap `/public-api/matches` |\n| `demo_slap_resolve.py` | Try to resolve replay/demo URL from Demo-Slap match history by index; fail clearly if the API exposes only `jobId` |\n| `demo_slap_match_pick.py` | Pick a Demo-Slap match by index and return structured match info including `jobId` |\n| `demo_slap_analyze.py` | Submit a demo for analysis, poll until done, output highlights JSON |\n| `demo_slap_render.py` | Render one or more highlights, poll until done, output clip URL |\n| `demo_slap_common.py` | Shared utilities (config, API calls, state) |\n\n### Leetify\n| Script | Purpose |\n|--------|---------|\n| `leetify/leetify_matches.py` | List recent matches |\n| `leetify/leetify_resolve.py` | Resolve replay URL by username + match index |\n| `leetify/leetify_save_id.py` | Save username -> Steam64 ID mapping |\n| `leetify/leetify_common.py` | Shared Leetify utilities |\n\n### Match source selection\n- Prefer Leetify for recent match discovery when `LEETIFY_API_KEY` is available.\n- If `LEETIFY_API_KEY` is not configured but `DEMOSLAP_API_KEY` is available, use Demo-Slap match history from `/public-api/matches`.\n- Swagger: `https://api-doc.demo-slap.net/`\n- Treat Demo-Slap match history as the fallback discovery path for listing matches and selecting an existing analyzed match or replay context before analyze/render.\n\n## Runtime files\n\nUse these files as optional local runtime state during execution:\n- `data/state.json`\n- `data/highlights.json`\n- `data/history.log`\n- `data/steam_ids.json`\n- `data/config.json`\n\nThese files are runtime helpers for local operation and are not required to understand or inspect the skill package itself.\n\n`state.json` tracks the current operation:\n```json\n{\n  \"status\": \"idle|analyzing|rendering|done|error\",\n  \"job_id\": \"...\",\n  \"render_job_id\": \"...\",\n  \"chat_id\": \"telegram:182314856\",\n  \"clip_urls\": {\"highlight_id\": \"https://...\"},\n  \"pro"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn73589k2rv646tm107cp6d90s81g7xy\",\n  \"slug\": \"demo-slap\",\n  \"version\": \"0.1.4\",\n  \"publishedAt\": 1773552433100\n}"},{"path":"scripts/demo_slap_task.md","content":"# demo-slap task workflow\n\nRecommended OpenClaw runtime pattern:\n\n- do not manage the watchdog through shell cron commands\n- prefer OpenClaw's built-in cron tool when a deployment chooses to enable or disable a watchdog for a live run\n- treat watchdog configuration and any job id as deployment-specific, not globally hardcoded\n- when used, `DEMO_SLAP_WATCHDOG_JOB_ID` should be supplied by the deployment rather than embedded in the skill\n- use the shell helper only for local inspection of state/log/job references:\n\n```bash\nscripts/demo_slap_watchdog.sh status\nscripts/demo_slap_watchdog.sh tail\nscripts/demo_slap_watchdog.sh job\n```\n\nSuggested runtime workflow for assistants:\n1. Before analyze/render -> `cron.update(jobId=<watchdog>, enabled=true)` when a deployment watchdog is being used\n2. Start analyze/render\n3. Let the watchdog inspect state on a reasonable interval such as every 2 minutes\n4. After successful delivery or terminal error -> `cron.update(jobId=<watchdog>, enabled=false)` when the deployment watchdog was enabled for that run"},{"path":"skill-card.md","content":"## Description:\n\nGenerate CS2 highlights and fragmovies from demos using the Demo-Slap API, with optional Leetify integration and Demo-Slap match history fallback for recent match selection.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[jeminay](https://clawhub.ai/user/jeminay)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nExternal users and developers use this skill in OpenClaw environments to select CS2 matches, analyze demos, render highlight clips or fragmovies, and deliver MP4 clip URLs.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Sensitive API keys or runtime data may be kept in local configuration or data files.\n\nMitigation: Prefer environment-injected API keys, restrict access to the data directory, and avoid storing secrets in data/config.json.\n\nRisk: Untrusted job, chat, and clip data can be published into OpenClaw system events.\n\nMitigation: Use typed events or validated and redacted fields before enabling automatic delivery actions.\n\nRisk: Background watchdog jobs can continue beyond the intended render or analysis run if left enabled.\n\nMitigation: Avoid watchdog jobs when possible; when needed, scope them to the active run and disable them after terminal delivery or error.\n\n## Reference(s):\n\n- [Demo Slap on ClawHub](https://clawhub.ai/jeminay/skills/demo-slap)\n- [Demo-Slap API Swagger](https://api-doc.demo-slap.net/)\n- [Demo-Slap API](https://api.demo-slap.net)\n- [Leetify Public API](https://api-public.cs-prod.leetify.com)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, shell commands, configuration, JSON, files]\n\n**Output Format:** [Markdown guidance with inline shell commands, JSON script output, runtime state files, and MP4 clip URLs]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Requires DEMOSLAP_API_KEY; can use LEETIFY_API_KEY for match discovery and OpenClaw for background notification workflows.]\n\n## Skill Version(s):\n\n0.1.4 (source: server release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment."}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":1268,"uniquenessScore":44,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-11T04:13:48.246Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-11T04:13:48.246Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-11T07:41:55.582Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}