{
  "schemaVersion": "1.0",
  "item": {
    "slug": "briefing-room",
    "name": "Briefing Room",
    "source": "tencent",
    "type": "skill",
    "category": "内容创作",
    "sourceUrl": "https://clawhub.ai/matusvojtek/briefing-room",
    "canonicalUrl": "https://clawhub.ai/matusvojtek/briefing-room",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/briefing-room",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=briefing-room",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "CHANGELOG.md",
      "README.md",
      "SKILL.md",
      "scripts/briefing.sh",
      "scripts/config.py"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-23T16:43:11.935Z",
      "expiresAt": "2026-04-30T16:43:11.935Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=4claw-imageboard",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=4claw-imageboard",
        "contentDisposition": "attachment; filename=\"4claw-imageboard-1.0.1.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/briefing-room"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/briefing-room",
    "agentPageUrl": "https://openagent3.xyz/skills/briefing-room/agent",
    "manifestUrl": "https://openagent3.xyz/skills/briefing-room/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/briefing-room/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "Briefing Room 📻",
        "body": "Your personal daily news briefing — audio + document.\n\nOn demand, research and compose a comprehensive ~10 minute news briefing in a conversational radio-host style. Output: audio file (MP3) + formatted document (DOCX)."
      },
      {
        "title": "💸 100% Free",
        "body": "No subscriptions, API keys, or paid services\nUses free public APIs (Open-Meteo weather, Coinbase prices, Google Trends RSS), web search, and local TTS\nTTS is fully local, no keys needed: MLX-Audio Kokoro (English) or Apple say (any language)\nReads/writes: ~/.briefing-room/config.json (settings) and ~/Documents/Briefing Room/ (output)"
      },
      {
        "title": "First-Run Setup",
        "body": "On first use, check if ~/.briefing-room/config.json exists. If not, run:\n\npython3 SKILL_DIR/scripts/config.py init\n\nThis creates default config. The user can customize:\n\nLocation — city, latitude, longitude, timezone (for weather)\nLanguage — en, sk, de, etc.\nVoices — per-language TTS engine and voice selection\nSections — which news sections to include\nOutput folder — where briefings are saved\n\nShow setup status:\n\npython3 SKILL_DIR/scripts/config.py status"
      },
      {
        "title": "Quick Start",
        "body": "When user asks for a briefing (e.g. \"give me a briefing\", \"morning update\", \"what's happening today\"):\n\nCheck config exists (run setup if not)\nPlay notification sound: afplay /System/Library/Sounds/Blow.aiff &\nSpawn a sub-agent with the full pipeline task immediately\nReply: \"📻 Briefing Room is firing up — gathering today's news. I'll ping you when it's ready!\"\nDO NOT BLOCK — spawn and move on instantly\n\nLanguage override: If user says \"po slovensky\", \"v slovenčine\", \"auf deutsch\", \"en français\", etc. → pass that to the sub-agent. Otherwise use the configured default language. Any language macOS supports will work — the agent writes the script in that language and TTS auto-detects a matching voice."
      },
      {
        "title": "Spawn Command",
        "body": "sessions_spawn(\n  task=\"<full pipeline instructions — see below>\",\n  label=\"briefing-room\",\n  runTimeoutSeconds=600,\n  cleanup=\"delete\"\n)\n\nThe task message should include ALL the pipeline steps below so the sub-agent is fully self-contained. Replace all SKILL_DIR references with the actual absolute path to this skill's directory.\n\nHost name: Read host.name from config. If empty, use your own agent name (from your identity). Pass it to the sub-agent as the radio host name (e.g. \"Good morning, I'm Jackie, and this is your Briefing Room...\")."
      },
      {
        "title": "Configuration",
        "body": "Config file: ~/.briefing-room/config.json\n\nRead values:\n\npython3 SKILL_DIR/scripts/config.py get location.city\npython3 SKILL_DIR/scripts/config.py get language\npython3 SKILL_DIR/scripts/config.py get voices.en.mlx_voice\n\nSet values:\n\npython3 SKILL_DIR/scripts/config.py set location.city \"Vienna\"\npython3 SKILL_DIR/scripts/config.py set location.latitude 48.21\npython3 SKILL_DIR/scripts/config.py set location.longitude 16.37\npython3 SKILL_DIR/scripts/config.py set language \"de\""
      },
      {
        "title": "Key Config Options",
        "body": "KeyDefaultDescriptionlocation.cityBratislavaCity name for weather + local newslocation.latitude48.15Weather API latitudelocation.longitude17.11Weather API longitudelocation.timezoneEurope/BratislavaTimezone for weather APIlanguageenDefault briefing languageoutput.folder~/Documents/Briefing RoomOutput directoryaudio.enabledtrueGenerate audioaudio.formatmp3Audio format (mp3, wav, aiff)audio.tts_engineautoTTS engine (auto, mlx, kokoro, builtin)sectionsall 11 (see below)Which sections to includehost.name(empty = agent name)Radio host name for the briefingtrends.regionsunited-states,united-kingdom,X/Twitter trend regions (comma-separated, trailing comma = worldwide)webtrends.regionsUS,GB,Google Trends regions (ISO codes, trailing comma = worldwide)"
      },
      {
        "title": "Voice Configuration Per Language",
        "body": "Each language can have its own TTS engine and voice:\n\n{\n  \"voices\": {\n    \"en\": {\n      \"engine\": \"mlx\",\n      \"mlx_voice\": \"af_heart\",\n      \"mlx_voice_blend\": {\"af_heart\": 0.6, \"af_sky\": 0.4},\n      \"builtin_voice\": \"Samantha\",\n      \"speed\": 1.05\n    },\n    \"sk\": {\n      \"engine\": \"builtin\",\n      \"builtin_voice\": \"Laura (Enhanced)\",\n      \"builtin_rate\": 220\n    },\n    \"de\": {\n      \"engine\": \"builtin\",\n      \"builtin_voice\": \"Petra (Premium)\",\n      \"builtin_rate\": 200\n    }\n  }\n}\n\nEngine priority (when auto):\n\nEnglish: mlx → kokoro → builtin\nOther languages: builtin (Apple TTS has good multilingual voices)\n\nUsers can add any language by adding a voices entry + a matching builtin_voice from say -v '?'."
      },
      {
        "title": "Output Structure",
        "body": "~/Documents/Briefing Room/YYYY-MM-DD/\n├── briefing-YYYY-MM-DD-HHMM.docx    # Formatted document\n└── briefing-YYYY-MM-DD-HHMM.mp3     # Audio briefing (~10 min)\n\nDo NOT save the .md working file in the output folder. Use /tmp/ for working files, delete after."
      },
      {
        "title": "Step 0: Setup",
        "body": "# Read config\nCITY=$(python3 SKILL_DIR/scripts/config.py get location.city)\nLAT=$(python3 SKILL_DIR/scripts/config.py get location.latitude)\nLON=$(python3 SKILL_DIR/scripts/config.py get location.longitude)\nTZ=$(python3 SKILL_DIR/scripts/config.py get location.timezone)\nLANG=$(python3 SKILL_DIR/scripts/config.py get language)\nOUTPUT_FOLDER=$(python3 SKILL_DIR/scripts/config.py get output.folder)\n\nDATE=$(date +%Y-%m-%d)\nTIMESTAMP=$(date +%Y-%m-%d-%H%M)\nOUTPUT_DIR=\"$OUTPUT_FOLDER/$DATE\"\nmkdir -p \"$OUTPUT_DIR\""
      },
      {
        "title": "Step 1: Gather Data — Weather",
        "body": "Use the configured location coordinates:\n\n# Current weather\nTZ_ENC=\"${TZ/\\//%2F}\"\nBASE=\"https://api.open-meteo.com/v1/forecast\"\nCURRENT=\"temperature_2m,relative_humidity_2m\"\nCURRENT=\"$CURRENT,apparent_temperature,precipitation\"\nCURRENT=\"$CURRENT,weather_code,wind_speed_10m\"\ncurl -s \"$BASE?latitude=$LAT&longitude=$LON\\\n&current=$CURRENT&timezone=$TZ_ENC\"\n\n# 7-day forecast\nDAILY=\"temperature_2m_max,temperature_2m_min\"\nDAILY=\"$DAILY,precipitation_sum,weather_code\"\ncurl -s \"$BASE?latitude=$LAT&longitude=$LON\\\n&daily=$DAILY&timezone=$TZ_ENC\"\n\nOr use the helper: bash SKILL_DIR/scripts/briefing.sh weather\n\nMap weather_code to descriptions:\n\n0: Clear sky ☀️\n1-3: Partly cloudy ⛅\n45-48: Fog 🌫️\n51-55: Drizzle 🌦️\n61-65: Rain 🌧️\n71-75: Snow ❄️\n80-82: Rain showers 🌦️\n95-99: Thunderstorm ⛈️"
      },
      {
        "title": "Step 2: Gather Data — News (Web Search)",
        "body": "Use web_search tool for each section. Add current date to queries for freshness. Use the configured $CITY for local news.\n\nX/Twitter Trends (from getdaytrends.com — real-time, no API key):\n\nbash SKILL_DIR/scripts/briefing.sh trends\n\nThis fetches top 25 trends from US, UK, and Worldwide. Use the output to:\n\nIdentify the most interesting/newsworthy trends (skip generic ones like \"Good Tuesday\", \"Taco Tuesday\")\nFilter out non-Latin script trends unless they're globally significant\nPick ~5-10 trends that overlap across regions or seem newsworthy\nUse web_search to get context on the top trends you selected\n\nWeb Trends (from Google Trends RSS — what people are searching):\n\nbash SKILL_DIR/scripts/briefing.sh webtrends\n\nThis fetches trending Google searches from US, UK, and Worldwide with:\n\nSearch term and approximate traffic volume\nTop news headline explaining why it's trending\nUse this data for the Web Trends section. The headlines already provide context — no extra searching needed for most items.\n\nWorld News:\n\nweb_search(\"top world news today {date}\", count=8)\nweb_search(\"breaking news today\", count=5)\n\nPolitics:\n\nweb_search(\"US politics news today {date}\", count=5)\nweb_search(\"EU politics news today {date}\", count=5)\nweb_search(\"geopolitics news today\", count=5)\n\n⚠️ Source diversity: All sources have bias. For balanced reporting:\n\nSearch the same story with different framing\nPresent what happened factually, note what each side says\nDon't adopt any outlet's framing as truth\nStick to verifiable facts: numbers, dates, quotes, actions\n\nTech & AI:\n\nweb_search(\"tech news today {date}\", count=5)\nweb_search(\"AI artificial intelligence news today {date}\", count=5)\n\nLocal news (based on configured city):\n\nweb_search(\"$CITY news today {date}\", count=5)\n\nAlso search in the configured language if not English:\n\nweb_search(\"$CITY [news today] in $LANG {date}\", count=5)\n\nExamples:\n\nSlovak: \"Bratislava správy dnes\"\nGerman: \"Wien Nachrichten heute\"\nCzech: \"Praha zprávy dnes\"\n\nSports:\n\nweb_search(\"sports news today {date}\", count=5)\nweb_search(\"football soccer results today\", count=5)"
      },
      {
        "title": "Step 3: Gather Data — Markets & Crypto (APIs + Search)",
        "body": "# Or use helper:\nbash SKILL_DIR/scripts/briefing.sh crypto\n\ncurl -s \"https://api.coinbase.com/v2/prices/BTC-USD/spot\"\ncurl -s \"https://api.coinbase.com/v2/prices/ETH-USD/spot\"\ncurl -s \"https://api.coinbase.com/v2/prices/SOL-USD/spot\"\ncurl -s \"https://api.coinbase.com/v2/prices/XRP-USD/spot\"\n\nweb_search(\"S&P 500 Dow Jones Nasdaq today {date}\", count=5)\nweb_search(\"stock market today movers {date}\", count=5)\nweb_search(\"gold price silver price today\", count=3)\nweb_search(\"crypto market today {date}\", count=5)"
      },
      {
        "title": "Step 4: Compose the Briefing Script",
        "body": "Write as a conversational radio-host monologue.\n\nStyle guidelines:\n\nWrite like a smart, engaging radio host — NOT a list of headlines\nUse the host name — introduce yourself: \"Good morning, I'm [host name], and this is your Briefing Room for [date]...\"\nSprinkle the name naturally throughout (sign-off, transitions) — don't overdo it\nDo NOT start markdown with a # Title header — pandoc adds title from metadata\nConnect stories with transitions\nAdd context: \"here's why this matters\"\nStay neutral and balanced — report facts, present sides, let listener decide\nTarget ~2,500-3,500 words for ~10 minutes\nNo emojis in the script (break TTS)\nWrite out numbers/abbreviations for TTS:\n\n\"$96,500\" → \"ninety-six thousand five hundred dollars\"\n\"S&P 500\" → \"S and P 500\"\n\"BTC\" → \"Bitcoin\"\n\"°C\" → \"degrees celsius\"\n\nIf language is not English, write the entire script in that language.\n\nSection order:\n\nOpening — Date, quick teaser of top stories\nWeather — Current + week outlook for configured city\nTrending on X — What's hot on X/Twitter\nWeb Trends — What people are searching (Google Trends)\nWorld — Top 3-5 global stories\nPolitics — US, EU, geopolitics\nTech & AI — Launches, breakthroughs\nLocal — News for configured city/country\nSports — Headlines, results\nMarkets — S&P 500, Dow, Nasdaq, movers\nCrypto & Commodities — BTC, ETH, alts, gold, silver\nThis Day in History — 1-2 interesting events that happened on this date\nClosing — Wrap-up, sign-off\n\nThis Day in History: No research needed — use your own knowledge. Pick 1-2 interesting, surprising, or fun events that happened on today's date. Mix it up: science, culture, politics, weird stuff. Keep it conversational: \"And before I let you go — did you know that on this day in 1996...\"\n\nOnly include sections from the configured sections list. Skip sections the user has removed.\n\nSave as /tmp/briefing_draft_$TIMESTAMP.md (working file).\n\nFor the markdown, include:\n\nSection headers with emojis: ## 🌤️ Weather, ## 🌍 World, ## 📜 This Day in History, etc.\nSource links after key facts\nKey data in bold"
      },
      {
        "title": "Step 5: Generate DOCX",
        "body": "pandoc \"/tmp/briefing_draft_$TIMESTAMP.md\" \\\n  -o \"$OUTPUT_DIR/briefing-$TIMESTAMP.docx\" \\\n  --metadata title=\"Briefing Room - $DATE\"\n\nIf pandoc is not available, skip DOCX and note it."
      },
      {
        "title": "Step 6: Generate Audio",
        "body": "Read the config to determine TTS engine and voice for the current language.\n\nMLX-Audio (English, or if configured for language):\n\npython3 SKILL_DIR/scripts/config.py get voices.$LANG.engine\n# → if \"mlx\":\n\nimport os, re, glob, json, subprocess\nfrom datetime import datetime\n\ntimestamp = datetime.now().strftime(\"%Y-%m-%d-%H%M\")  # must match TIMESTAMP from Step 0\n\n# Read config\nconfig_path = os.path.expanduser(\"~/.briefing-room/config.json\")\nwith open(config_path) as f:\n    config = json.load(f)\n\nlang = config.get(\"language\", \"en\")\nvoices = config.get(\"voices\", {})\nvoice_cfg = voices.get(lang, voices.get(\"en\", {}))\n\n# Read and strip markdown from draft\nwith open(f\"/tmp/briefing_draft_{timestamp}.md\", \"r\") as f:\n    text = f.read()\ntext = re.sub(r'#+ ', '', text)\ntext = re.sub(r'\\*\\*([^*]+)\\*\\*', r'\\1', text)\ntext = re.sub(r'\\*([^*]+)\\*', r'\\1', text)\ntext = re.sub(r'\\[([^\\]]+)\\]\\([^)]+\\)', r'\\1', text)\ntext = re.sub(r'---+', '', text)\ntext = re.sub(r'\\n{3,}', '\\n\\n', text)\n\n# Resolve voice\nblend = voice_cfg.get(\"mlx_voice_blend\")\nvoice = voice_cfg.get(\"mlx_voice\", \"af_heart\")\nif blend:\n    model = config.get(\"mlx_audio\", {}).get(\"model\", \"mlx-community/Kokoro-82M-bf16\")\n    model_slug = model.replace(\"/\", \"--\")\n    cache_dir = os.path.expanduser(f\"~/.cache/huggingface/hub/models--{model_slug}\")\n    parts = []\n    for v, w in sorted(blend.items(), key=lambda x: -x[1]):\n        parts.append(f\"{v}_{int(w * 100)}\")\n    blend_name = \"_\".join(parts) + \".safetensors\"\n    matches = glob.glob(os.path.join(cache_dir, \"snapshots/*/voices\", blend_name))\n    if matches:\n        voice = matches[0]\n\nspeed = voice_cfg.get(\"speed\", 1.05)\nlang_code = config.get(\"mlx_audio\", {}).get(\"lang_code\", \"a\")\n\n# Find MLX-Audio\nmlx_path = config.get(\"mlx_audio\", {}).get(\"path\", \"\")\nif not mlx_path:\n    for p in [\"~/.openclaw/tools/mlx-audio\", \"~/.local/share/mlx-audio\"]:\n        ep = os.path.expanduser(p)\n        if os.path.exists(os.path.join(ep, \".venv/bin/python3\")):\n            mlx_path = ep\n            break\n\n# Generate via subprocess (uses MLX-Audio's venv)\npython_bin = os.path.join(mlx_path, \".venv/bin/python3\")\n# ... generate_audio call with resolved voice, speed, lang_code\n\nBuilt-in Apple TTS (any language):\n\nIf there's no voice configured for the language, auto-detect one:\n\n# Try to get configured voice, fall back to auto-detect\nVOICE=$(python3 SKILL_DIR/scripts/config.py get voices.$LANG.builtin_voice)\nif [ \"$VOICE\" = \"None\" ] || [ -z \"$VOICE\" ]; then\n    # Auto-detect: match locale (e.g. sk_SK, de_DE, fr_FR)\n    # Prefer Enhanced/Premium voices, fall back to any\n    VOICE=$(say -v '?' | grep \"${LANG}_\" \\\n      | grep -i \"Enhanced\\|Premium\" | head -1 \\\n      | sed 's/ *[a-z][a-z]_[A-Z][A-Z].*//' | xargs)\n    [ -z \"$VOICE\" ] && VOICE=$(say -v '?' \\\n      | grep \"${LANG}_\" | head -1 \\\n      | sed 's/ *[a-z][a-z]_[A-Z][A-Z].*//' | xargs)\nfi\nRATE=$(python3 SKILL_DIR/scripts/config.py get voices.$LANG.builtin_rate)\n# Strip markdown for TTS\nDRAFT=\"/tmp/briefing_draft_$TIMESTAMP.md\"\nTTS_TXT=\"/tmp/briefing_tts_$TIMESTAMP.txt\"\nsed -E 's/#+//g; s/\\*+//g; s/\\[([^]]*)\\]\\([^)]*\\)/\\1/g' \\\n  \"$DRAFT\" > \"$TTS_TXT\"\nsay -v \"$VOICE\" ${RATE:+-r $RATE} \\\n  -o \"$OUTPUT_DIR/briefing-$TIMESTAMP.aiff\" \\\n  -f \"$TTS_TXT\"\nrm -f \"/tmp/briefing_tts_$TIMESTAMP.txt\"\n\nKokoro PyTorch (fallback):\n\nSimilar to MLX but uses PyTorch backend. See TubeScribe skill for Kokoro usage patterns."
      },
      {
        "title": "Step 6b: Convert to MP3",
        "body": "# Find the raw audio file (MLX outputs .wav, Apple TTS outputs .aiff)\nRAW=\"\"\nfor ext in wav aiff; do\n    if [ -f \"$OUTPUT_DIR/briefing-$TIMESTAMP.$ext\" ]; then\n        RAW=\"$OUTPUT_DIR/briefing-$TIMESTAMP.$ext\"\n        break\n    fi\ndone\n\nif [ -n \"$RAW\" ]; then\n    ffmpeg -y \\\n      -i \"$RAW\" \\\n      -codec:a libmp3lame -qscale:a 2 \\\n      \"$OUTPUT_DIR/briefing-$TIMESTAMP.mp3\"\n    if [ -s \"$OUTPUT_DIR/briefing-$TIMESTAMP.mp3\" ]; then\n        rm \"$RAW\"\n    fi\nfi"
      },
      {
        "title": "Step 6c: Cleanup",
        "body": "rm -f \"/tmp/briefing_draft_$TIMESTAMP.md\""
      },
      {
        "title": "Step 7: Open Output Folder",
        "body": "open \"$OUTPUT_DIR\"\n\nDo NOT auto-play. Briefings are long and need playback controls."
      },
      {
        "title": "Step 8: Report",
        "body": "Report back with:\n\nDate and language of briefing\nSections covered\nTop 3-4 headlines\nAudio duration\nFile locations"
      },
      {
        "title": "Helper Script",
        "body": "bash SKILL_DIR/scripts/briefing.sh setup     # Check dependencies + config\nbash SKILL_DIR/scripts/briefing.sh weather    # Fetch weather (uses config location)\nbash SKILL_DIR/scripts/briefing.sh trends     # Fetch X/Twitter trends (US + UK + Worldwide)\nbash SKILL_DIR/scripts/briefing.sh webtrends  # Fetch Google Trends (US + UK + Worldwide)\nbash SKILL_DIR/scripts/briefing.sh crypto     # Fetch crypto prices\nbash SKILL_DIR/scripts/briefing.sh open       # Open today's folder\nbash SKILL_DIR/scripts/briefing.sh list       # List all briefings\nbash SKILL_DIR/scripts/briefing.sh clean      # Remove briefings >30 days old\nbash SKILL_DIR/scripts/briefing.sh config     # Show raw config JSON"
      },
      {
        "title": "Tips",
        "body": "Full pipeline takes 3-5 minutes (research + composition + TTS)\nFor shorter briefing, say \"quick briefing\" — cover top 3 sections only\nIf markets are closed (weekend/holiday), note it and skip detailed data\nThe agent IS the intelligence — read search results, compose the script, decide what matters\nUsers can add new languages by adding a voices entry + installing the voice via say -v '?'"
      },
      {
        "title": "Dependencies",
        "body": "Required:\n\ncurl — API calls (built into macOS)\nweb_search tool — News research (OpenClaw built-in)\n\nRecommended:\n\nMLX-Audio Kokoro — fast English TTS\npandoc — DOCX generation: brew install pandoc\nffmpeg — MP3 conversion: brew install ffmpeg\n\nBuilt-in (macOS):\n\nApple say — multilingual TTS (always available as fallback)"
      },
      {
        "title": "Error Handling",
        "body": "IssueActionNo config fileRun python3 SKILL_DIR/scripts/config.py initAPI timeoutRetry once, skip that source, note itWeb search emptyTry alternative query, note gapsTTS failsFall back to Apple say (always available)Pandoc not foundSkip DOCX, deliver MP3 onlyNo internetCannot generate — inform user"
      }
    ],
    "body": "Briefing Room 📻\n\nYour personal daily news briefing — audio + document.\n\nOn demand, research and compose a comprehensive ~10 minute news briefing in a conversational radio-host style. Output: audio file (MP3) + formatted document (DOCX).\n\n💸 100% Free\nNo subscriptions, API keys, or paid services\nUses free public APIs (Open-Meteo weather, Coinbase prices, Google Trends RSS), web search, and local TTS\nTTS is fully local, no keys needed: MLX-Audio Kokoro (English) or Apple say (any language)\nReads/writes: ~/.briefing-room/config.json (settings) and ~/Documents/Briefing Room/ (output)\nFirst-Run Setup\n\nOn first use, check if ~/.briefing-room/config.json exists. If not, run:\n\npython3 SKILL_DIR/scripts/config.py init\n\n\nThis creates default config. The user can customize:\n\nLocation — city, latitude, longitude, timezone (for weather)\nLanguage — en, sk, de, etc.\nVoices — per-language TTS engine and voice selection\nSections — which news sections to include\nOutput folder — where briefings are saved\n\nShow setup status:\n\npython3 SKILL_DIR/scripts/config.py status\n\nQuick Start\n\nWhen user asks for a briefing (e.g. \"give me a briefing\", \"morning update\", \"what's happening today\"):\n\nCheck config exists (run setup if not)\nPlay notification sound: afplay /System/Library/Sounds/Blow.aiff &\nSpawn a sub-agent with the full pipeline task immediately\nReply: \"📻 Briefing Room is firing up — gathering today's news. I'll ping you when it's ready!\"\nDO NOT BLOCK — spawn and move on instantly\n\nLanguage override: If user says \"po slovensky\", \"v slovenčine\", \"auf deutsch\", \"en français\", etc. → pass that to the sub-agent. Otherwise use the configured default language. Any language macOS supports will work — the agent writes the script in that language and TTS auto-detects a matching voice.\n\nSpawn Command\nsessions_spawn(\n  task=\"<full pipeline instructions — see below>\",\n  label=\"briefing-room\",\n  runTimeoutSeconds=600,\n  cleanup=\"delete\"\n)\n\n\nThe task message should include ALL the pipeline steps below so the sub-agent is fully self-contained. Replace all SKILL_DIR references with the actual absolute path to this skill's directory.\n\nHost name: Read host.name from config. If empty, use your own agent name (from your identity). Pass it to the sub-agent as the radio host name (e.g. \"Good morning, I'm Jackie, and this is your Briefing Room...\").\n\nConfiguration\n\nConfig file: ~/.briefing-room/config.json\n\nRead values:\n\npython3 SKILL_DIR/scripts/config.py get location.city\npython3 SKILL_DIR/scripts/config.py get language\npython3 SKILL_DIR/scripts/config.py get voices.en.mlx_voice\n\n\nSet values:\n\npython3 SKILL_DIR/scripts/config.py set location.city \"Vienna\"\npython3 SKILL_DIR/scripts/config.py set location.latitude 48.21\npython3 SKILL_DIR/scripts/config.py set location.longitude 16.37\npython3 SKILL_DIR/scripts/config.py set language \"de\"\n\nKey Config Options\nKey\tDefault\tDescription\nlocation.city\tBratislava\tCity name for weather + local news\nlocation.latitude\t48.15\tWeather API latitude\nlocation.longitude\t17.11\tWeather API longitude\nlocation.timezone\tEurope/Bratislava\tTimezone for weather API\nlanguage\ten\tDefault briefing language\noutput.folder\t~/Documents/Briefing Room\tOutput directory\naudio.enabled\ttrue\tGenerate audio\naudio.format\tmp3\tAudio format (mp3, wav, aiff)\naudio.tts_engine\tauto\tTTS engine (auto, mlx, kokoro, builtin)\nsections\tall 11 (see below)\tWhich sections to include\nhost.name\t(empty = agent name)\tRadio host name for the briefing\ntrends.regions\tunited-states,united-kingdom,\tX/Twitter trend regions (comma-separated, trailing comma = worldwide)\nwebtrends.regions\tUS,GB,\tGoogle Trends regions (ISO codes, trailing comma = worldwide)\nVoice Configuration Per Language\n\nEach language can have its own TTS engine and voice:\n\n{\n  \"voices\": {\n    \"en\": {\n      \"engine\": \"mlx\",\n      \"mlx_voice\": \"af_heart\",\n      \"mlx_voice_blend\": {\"af_heart\": 0.6, \"af_sky\": 0.4},\n      \"builtin_voice\": \"Samantha\",\n      \"speed\": 1.05\n    },\n    \"sk\": {\n      \"engine\": \"builtin\",\n      \"builtin_voice\": \"Laura (Enhanced)\",\n      \"builtin_rate\": 220\n    },\n    \"de\": {\n      \"engine\": \"builtin\",\n      \"builtin_voice\": \"Petra (Premium)\",\n      \"builtin_rate\": 200\n    }\n  }\n}\n\n\nEngine priority (when auto):\n\nEnglish: mlx → kokoro → builtin\nOther languages: builtin (Apple TTS has good multilingual voices)\n\nUsers can add any language by adding a voices entry + a matching builtin_voice from say -v '?'.\n\nOutput Structure\n~/Documents/Briefing Room/YYYY-MM-DD/\n├── briefing-YYYY-MM-DD-HHMM.docx    # Formatted document\n└── briefing-YYYY-MM-DD-HHMM.mp3     # Audio briefing (~10 min)\n\n\nDo NOT save the .md working file in the output folder. Use /tmp/ for working files, delete after.\n\nFull Pipeline\nStep 0: Setup\n# Read config\nCITY=$(python3 SKILL_DIR/scripts/config.py get location.city)\nLAT=$(python3 SKILL_DIR/scripts/config.py get location.latitude)\nLON=$(python3 SKILL_DIR/scripts/config.py get location.longitude)\nTZ=$(python3 SKILL_DIR/scripts/config.py get location.timezone)\nLANG=$(python3 SKILL_DIR/scripts/config.py get language)\nOUTPUT_FOLDER=$(python3 SKILL_DIR/scripts/config.py get output.folder)\n\nDATE=$(date +%Y-%m-%d)\nTIMESTAMP=$(date +%Y-%m-%d-%H%M)\nOUTPUT_DIR=\"$OUTPUT_FOLDER/$DATE\"\nmkdir -p \"$OUTPUT_DIR\"\n\nStep 1: Gather Data — Weather\n\nUse the configured location coordinates:\n\n# Current weather\nTZ_ENC=\"${TZ/\\//%2F}\"\nBASE=\"https://api.open-meteo.com/v1/forecast\"\nCURRENT=\"temperature_2m,relative_humidity_2m\"\nCURRENT=\"$CURRENT,apparent_temperature,precipitation\"\nCURRENT=\"$CURRENT,weather_code,wind_speed_10m\"\ncurl -s \"$BASE?latitude=$LAT&longitude=$LON\\\n&current=$CURRENT&timezone=$TZ_ENC\"\n\n# 7-day forecast\nDAILY=\"temperature_2m_max,temperature_2m_min\"\nDAILY=\"$DAILY,precipitation_sum,weather_code\"\ncurl -s \"$BASE?latitude=$LAT&longitude=$LON\\\n&daily=$DAILY&timezone=$TZ_ENC\"\n\n\nOr use the helper: bash SKILL_DIR/scripts/briefing.sh weather\n\nMap weather_code to descriptions:\n\n0: Clear sky ☀️\n1-3: Partly cloudy ⛅\n45-48: Fog 🌫️\n51-55: Drizzle 🌦️\n61-65: Rain 🌧️\n71-75: Snow ❄️\n80-82: Rain showers 🌦️\n95-99: Thunderstorm ⛈️\nStep 2: Gather Data — News (Web Search)\n\nUse web_search tool for each section. Add current date to queries for freshness. Use the configured $CITY for local news.\n\nX/Twitter Trends (from getdaytrends.com — real-time, no API key):\n\nbash SKILL_DIR/scripts/briefing.sh trends\n\n\nThis fetches top 25 trends from US, UK, and Worldwide. Use the output to:\n\nIdentify the most interesting/newsworthy trends (skip generic ones like \"Good Tuesday\", \"Taco Tuesday\")\nFilter out non-Latin script trends unless they're globally significant\nPick ~5-10 trends that overlap across regions or seem newsworthy\nUse web_search to get context on the top trends you selected\n\nWeb Trends (from Google Trends RSS — what people are searching):\n\nbash SKILL_DIR/scripts/briefing.sh webtrends\n\n\nThis fetches trending Google searches from US, UK, and Worldwide with:\n\nSearch term and approximate traffic volume\nTop news headline explaining why it's trending Use this data for the Web Trends section. The headlines already provide context — no extra searching needed for most items.\n\nWorld News:\n\nweb_search(\"top world news today {date}\", count=8)\nweb_search(\"breaking news today\", count=5)\n\n\nPolitics:\n\nweb_search(\"US politics news today {date}\", count=5)\nweb_search(\"EU politics news today {date}\", count=5)\nweb_search(\"geopolitics news today\", count=5)\n\n\n⚠️ Source diversity: All sources have bias. For balanced reporting:\n\nSearch the same story with different framing\nPresent what happened factually, note what each side says\nDon't adopt any outlet's framing as truth\nStick to verifiable facts: numbers, dates, quotes, actions\n\nTech & AI:\n\nweb_search(\"tech news today {date}\", count=5)\nweb_search(\"AI artificial intelligence news today {date}\", count=5)\n\n\nLocal news (based on configured city):\n\nweb_search(\"$CITY news today {date}\", count=5)\n\n\nAlso search in the configured language if not English:\n\nweb_search(\"$CITY [news today] in $LANG {date}\", count=5)\n\n\nExamples:\n\nSlovak: \"Bratislava správy dnes\"\nGerman: \"Wien Nachrichten heute\"\nCzech: \"Praha zprávy dnes\"\n\nSports:\n\nweb_search(\"sports news today {date}\", count=5)\nweb_search(\"football soccer results today\", count=5)\n\nStep 3: Gather Data — Markets & Crypto (APIs + Search)\n# Or use helper:\nbash SKILL_DIR/scripts/briefing.sh crypto\n\ncurl -s \"https://api.coinbase.com/v2/prices/BTC-USD/spot\"\ncurl -s \"https://api.coinbase.com/v2/prices/ETH-USD/spot\"\ncurl -s \"https://api.coinbase.com/v2/prices/SOL-USD/spot\"\ncurl -s \"https://api.coinbase.com/v2/prices/XRP-USD/spot\"\n\nweb_search(\"S&P 500 Dow Jones Nasdaq today {date}\", count=5)\nweb_search(\"stock market today movers {date}\", count=5)\nweb_search(\"gold price silver price today\", count=3)\nweb_search(\"crypto market today {date}\", count=5)\n\nStep 4: Compose the Briefing Script\n\nWrite as a conversational radio-host monologue.\n\nStyle guidelines:\n\nWrite like a smart, engaging radio host — NOT a list of headlines\nUse the host name — introduce yourself: \"Good morning, I'm [host name], and this is your Briefing Room for [date]...\"\nSprinkle the name naturally throughout (sign-off, transitions) — don't overdo it\nDo NOT start markdown with a # Title header — pandoc adds title from metadata\nConnect stories with transitions\nAdd context: \"here's why this matters\"\nStay neutral and balanced — report facts, present sides, let listener decide\nTarget ~2,500-3,500 words for ~10 minutes\nNo emojis in the script (break TTS)\nWrite out numbers/abbreviations for TTS:\n\"$96,500\" → \"ninety-six thousand five hundred dollars\"\n\"S&P 500\" → \"S and P 500\"\n\"BTC\" → \"Bitcoin\"\n\"°C\" → \"degrees celsius\"\n\nIf language is not English, write the entire script in that language.\n\nSection order:\n\nOpening — Date, quick teaser of top stories\nWeather — Current + week outlook for configured city\nTrending on X — What's hot on X/Twitter\nWeb Trends — What people are searching (Google Trends)\nWorld — Top 3-5 global stories\nPolitics — US, EU, geopolitics\nTech & AI — Launches, breakthroughs\nLocal — News for configured city/country\nSports — Headlines, results\nMarkets — S&P 500, Dow, Nasdaq, movers\nCrypto & Commodities — BTC, ETH, alts, gold, silver\nThis Day in History — 1-2 interesting events that happened on this date\nClosing — Wrap-up, sign-off\n\nThis Day in History: No research needed — use your own knowledge. Pick 1-2 interesting, surprising, or fun events that happened on today's date. Mix it up: science, culture, politics, weird stuff. Keep it conversational: \"And before I let you go — did you know that on this day in 1996...\"\n\nOnly include sections from the configured sections list. Skip sections the user has removed.\n\nSave as /tmp/briefing_draft_$TIMESTAMP.md (working file).\n\nFor the markdown, include:\n\nSection headers with emojis: ## 🌤️ Weather, ## 🌍 World, ## 📜 This Day in History, etc.\nSource links after key facts\nKey data in bold\nStep 5: Generate DOCX\npandoc \"/tmp/briefing_draft_$TIMESTAMP.md\" \\\n  -o \"$OUTPUT_DIR/briefing-$TIMESTAMP.docx\" \\\n  --metadata title=\"Briefing Room - $DATE\"\n\n\nIf pandoc is not available, skip DOCX and note it.\n\nStep 6: Generate Audio\n\nRead the config to determine TTS engine and voice for the current language.\n\nMLX-Audio (English, or if configured for language):\n\npython3 SKILL_DIR/scripts/config.py get voices.$LANG.engine\n# → if \"mlx\":\n\nimport os, re, glob, json, subprocess\nfrom datetime import datetime\n\ntimestamp = datetime.now().strftime(\"%Y-%m-%d-%H%M\")  # must match TIMESTAMP from Step 0\n\n# Read config\nconfig_path = os.path.expanduser(\"~/.briefing-room/config.json\")\nwith open(config_path) as f:\n    config = json.load(f)\n\nlang = config.get(\"language\", \"en\")\nvoices = config.get(\"voices\", {})\nvoice_cfg = voices.get(lang, voices.get(\"en\", {}))\n\n# Read and strip markdown from draft\nwith open(f\"/tmp/briefing_draft_{timestamp}.md\", \"r\") as f:\n    text = f.read()\ntext = re.sub(r'#+ ', '', text)\ntext = re.sub(r'\\*\\*([^*]+)\\*\\*', r'\\1', text)\ntext = re.sub(r'\\*([^*]+)\\*', r'\\1', text)\ntext = re.sub(r'\\[([^\\]]+)\\]\\([^)]+\\)', r'\\1', text)\ntext = re.sub(r'---+', '', text)\ntext = re.sub(r'\\n{3,}', '\\n\\n', text)\n\n# Resolve voice\nblend = voice_cfg.get(\"mlx_voice_blend\")\nvoice = voice_cfg.get(\"mlx_voice\", \"af_heart\")\nif blend:\n    model = config.get(\"mlx_audio\", {}).get(\"model\", \"mlx-community/Kokoro-82M-bf16\")\n    model_slug = model.replace(\"/\", \"--\")\n    cache_dir = os.path.expanduser(f\"~/.cache/huggingface/hub/models--{model_slug}\")\n    parts = []\n    for v, w in sorted(blend.items(), key=lambda x: -x[1]):\n        parts.append(f\"{v}_{int(w * 100)}\")\n    blend_name = \"_\".join(parts) + \".safetensors\"\n    matches = glob.glob(os.path.join(cache_dir, \"snapshots/*/voices\", blend_name))\n    if matches:\n        voice = matches[0]\n\nspeed = voice_cfg.get(\"speed\", 1.05)\nlang_code = config.get(\"mlx_audio\", {}).get(\"lang_code\", \"a\")\n\n# Find MLX-Audio\nmlx_path = config.get(\"mlx_audio\", {}).get(\"path\", \"\")\nif not mlx_path:\n    for p in [\"~/.openclaw/tools/mlx-audio\", \"~/.local/share/mlx-audio\"]:\n        ep = os.path.expanduser(p)\n        if os.path.exists(os.path.join(ep, \".venv/bin/python3\")):\n            mlx_path = ep\n            break\n\n# Generate via subprocess (uses MLX-Audio's venv)\npython_bin = os.path.join(mlx_path, \".venv/bin/python3\")\n# ... generate_audio call with resolved voice, speed, lang_code\n\n\nBuilt-in Apple TTS (any language):\n\nIf there's no voice configured for the language, auto-detect one:\n\n# Try to get configured voice, fall back to auto-detect\nVOICE=$(python3 SKILL_DIR/scripts/config.py get voices.$LANG.builtin_voice)\nif [ \"$VOICE\" = \"None\" ] || [ -z \"$VOICE\" ]; then\n    # Auto-detect: match locale (e.g. sk_SK, de_DE, fr_FR)\n    # Prefer Enhanced/Premium voices, fall back to any\n    VOICE=$(say -v '?' | grep \"${LANG}_\" \\\n      | grep -i \"Enhanced\\|Premium\" | head -1 \\\n      | sed 's/ *[a-z][a-z]_[A-Z][A-Z].*//' | xargs)\n    [ -z \"$VOICE\" ] && VOICE=$(say -v '?' \\\n      | grep \"${LANG}_\" | head -1 \\\n      | sed 's/ *[a-z][a-z]_[A-Z][A-Z].*//' | xargs)\nfi\nRATE=$(python3 SKILL_DIR/scripts/config.py get voices.$LANG.builtin_rate)\n# Strip markdown for TTS\nDRAFT=\"/tmp/briefing_draft_$TIMESTAMP.md\"\nTTS_TXT=\"/tmp/briefing_tts_$TIMESTAMP.txt\"\nsed -E 's/#+//g; s/\\*+//g; s/\\[([^]]*)\\]\\([^)]*\\)/\\1/g' \\\n  \"$DRAFT\" > \"$TTS_TXT\"\nsay -v \"$VOICE\" ${RATE:+-r $RATE} \\\n  -o \"$OUTPUT_DIR/briefing-$TIMESTAMP.aiff\" \\\n  -f \"$TTS_TXT\"\nrm -f \"/tmp/briefing_tts_$TIMESTAMP.txt\"\n\n\nKokoro PyTorch (fallback):\n\nSimilar to MLX but uses PyTorch backend. See TubeScribe skill for Kokoro usage patterns.\n\nStep 6b: Convert to MP3\n# Find the raw audio file (MLX outputs .wav, Apple TTS outputs .aiff)\nRAW=\"\"\nfor ext in wav aiff; do\n    if [ -f \"$OUTPUT_DIR/briefing-$TIMESTAMP.$ext\" ]; then\n        RAW=\"$OUTPUT_DIR/briefing-$TIMESTAMP.$ext\"\n        break\n    fi\ndone\n\nif [ -n \"$RAW\" ]; then\n    ffmpeg -y \\\n      -i \"$RAW\" \\\n      -codec:a libmp3lame -qscale:a 2 \\\n      \"$OUTPUT_DIR/briefing-$TIMESTAMP.mp3\"\n    if [ -s \"$OUTPUT_DIR/briefing-$TIMESTAMP.mp3\" ]; then\n        rm \"$RAW\"\n    fi\nfi\n\nStep 6c: Cleanup\nrm -f \"/tmp/briefing_draft_$TIMESTAMP.md\"\n\nStep 7: Open Output Folder\nopen \"$OUTPUT_DIR\"\n\n\nDo NOT auto-play. Briefings are long and need playback controls.\n\nStep 8: Report\n\nReport back with:\n\nDate and language of briefing\nSections covered\nTop 3-4 headlines\nAudio duration\nFile locations\nHelper Script\nbash SKILL_DIR/scripts/briefing.sh setup     # Check dependencies + config\nbash SKILL_DIR/scripts/briefing.sh weather    # Fetch weather (uses config location)\nbash SKILL_DIR/scripts/briefing.sh trends     # Fetch X/Twitter trends (US + UK + Worldwide)\nbash SKILL_DIR/scripts/briefing.sh webtrends  # Fetch Google Trends (US + UK + Worldwide)\nbash SKILL_DIR/scripts/briefing.sh crypto     # Fetch crypto prices\nbash SKILL_DIR/scripts/briefing.sh open       # Open today's folder\nbash SKILL_DIR/scripts/briefing.sh list       # List all briefings\nbash SKILL_DIR/scripts/briefing.sh clean      # Remove briefings >30 days old\nbash SKILL_DIR/scripts/briefing.sh config     # Show raw config JSON\n\nTips\nFull pipeline takes 3-5 minutes (research + composition + TTS)\nFor shorter briefing, say \"quick briefing\" — cover top 3 sections only\nIf markets are closed (weekend/holiday), note it and skip detailed data\nThe agent IS the intelligence — read search results, compose the script, decide what matters\nUsers can add new languages by adding a voices entry + installing the voice via say -v '?'\nDependencies\n\nRequired:\n\ncurl — API calls (built into macOS)\nweb_search tool — News research (OpenClaw built-in)\n\nRecommended:\n\nMLX-Audio Kokoro — fast English TTS\npandoc — DOCX generation: brew install pandoc\nffmpeg — MP3 conversion: brew install ffmpeg\n\nBuilt-in (macOS):\n\nApple say — multilingual TTS (always available as fallback)\nError Handling\nIssue\tAction\nNo config file\tRun python3 SKILL_DIR/scripts/config.py init\nAPI timeout\tRetry once, skip that source, note it\nWeb search empty\tTry alternative query, note gaps\nTTS fails\tFall back to Apple say (always available)\nPandoc not found\tSkip DOCX, deliver MP3 only\nNo internet\tCannot generate — inform user"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/matusvojtek/briefing-room",
    "publisherUrl": "https://clawhub.ai/matusvojtek/briefing-room",
    "owner": "matusvojtek",
    "version": "1.0.3",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/briefing-room",
    "downloadUrl": "https://openagent3.xyz/downloads/briefing-room",
    "agentUrl": "https://openagent3.xyz/skills/briefing-room/agent",
    "manifestUrl": "https://openagent3.xyz/skills/briefing-room/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/briefing-room/agent.md"
  }
}