{"id":"4d8b69e5-37cb-4d9e-acbb-6ff4e691f57d","entityType":"agent","slug":"clawhub-axisrow-tg-channel-manager","name":"TG Channel Manager","canonicalUrl":"https://www.xpersona.co/agent/clawhub-axisrow-tg-channel-manager","canonicalPath":"/agent/clawhub-axisrow-tg-channel-manager","generatedAt":"2026-10-12T18:07:59.420Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"editorial-content","verified":true,"confidence":"high","updatedAt":"2026-10-11T21:13:22.414Z","emptyReason":null},"description":"Universal config-driven content pipeline engine for any Telegram channel: news search via SearXNG, drafts, scheduled publishing, deduplication. All channel s... Skill: TG Channel Manager Owner: axisrow Summary: Universal config-driven content pipeline engine for any Telegram channel: news search via SearXNG, drafts, scheduled publishing, deduplication. All channel s... Tags: automation:0.0.1, channel:0.0.1, content:0.0.1, latest:0.0.3, searxng:0.0.1, telegram:0.0.1 Version history: v0.0.3 | 2026-02-23T13:00:09.332Z | user tg-channel-manager 0.0.3 - Major refactor: new comman","descriptionLabel":"Technical summary","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 992 downloads reported by the source. Last updated 10/11/2026.","installCommand":"clawhub skill install s17d1epe9h78z9q1j01yd0yzt18856rc:tg-channel-manager","sourceUrl":"https://clawhub.ai/axisrow/tg-channel-manager","homepage":"https://clawhub.ai/axisrow/skills/tg-channel-manager","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/axisrow/tg-channel-manager","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/axisrow/skills/tg-channel-manager","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":60,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"Universal config-driven content pipeline engine for any Telegram channel: news search via SearXNG, drafts, scheduled publishing, deduplication. All channel s..."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-11T21:13:22.414Z","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-11T21:13:22.414Z","emptyReason":null},"stars":null,"forks":null,"downloads":992,"likes":null,"task":null,"library":null,"packageName":null,"latestVersion":"0.0.3","tractionLabel":"992 downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T21:13:22.350Z","emptyReason":null},"lastUpdatedAt":"2026-10-11T21:13:22.414Z","lastCrawledAt":"2026-10-11T21:13:22.350Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-12T21:13:22.350Z","lastVerifiedAt":null,"highlights":[{"version":"0.0.3","createdAt":"2026-02-23T13:00:09.332Z","changelog":"tg-channel-manager 0.0.3 - Major refactor: new command-line tool `tgcm.py`, replacing previous interface. - Full CLI defined: standardized commands for channel management, token/env setup, and index rebuilding. - New startup preflight check for required tokens, env, and channels with automatic issue reporting and fixes. - Configuration is now persistent via `tgcm/.config.json`. - Added sample and startup files: channels config example and helper scripts. - Old README.md removed, documentation migrated to SKILL.md and improved with step-by-step usage and strict DOs/DON'Ts.","fileCount":9,"zipByteSize":19316},{"version":"0.0.2","createdAt":"2026-02-21T16:47:02.027Z","changelog":"Translate all files to English, remove Cyrillic, rename from tg-content-manager","fileCount":7,"zipByteSize":8834},{"version":"0.0.1","createdAt":"2026-02-21T16:32:00.621Z","changelog":"Initial release: universal config-driven content pipeline for Telegram channels. - Scout cron: finds news via SearXNG, writes drafts to content-queue.md - Publisher cron: publishes approved posts to Telegram channel - Dedup engine: keyword + link matching against content-index.json - All channel specifics (queries, rubrics, style, filters) in openclaw.json config - Zero hardcoded values — one skill for any channel","fileCount":6,"zipByteSize":9705}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s17d1epe9h78z9q1j01yd0yzt18856rc:tg-channel-manager","setupComplexity":"low","setupSteps":["Setup complexity is LOW. This package is likely designed for quick installation with minimal external side-effects.","Final validation: Expose the agent to a mock request payload inside a sandbox and trace the network egress before allowing access to real customer data."],"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-axisrow-tg-channel-manager/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-axisrow-tg-channel-manager/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-axisrow-tg-channel-manager/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-axisrow-tg-channel-manager/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-axisrow-tg-channel-manager/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-axisrow-tg-channel-manager/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-12T18:07:59.420Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-axisrow-tg-channel-manager/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-axisrow-tg-channel-manager/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-axisrow-tg-channel-manager/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-axisrow-tg-channel-manager/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":"high","updatedAt":"2026-10-11T21:13:22.414Z","emptyReason":null},"readme":"Skill: TG Channel Manager\n\nOwner: axisrow\n\nSummary: Universal config-driven content pipeline engine for any Telegram channel: news search via SearXNG, drafts, scheduled publishing, deduplication. All channel s...\n\nTags: automation:0.0.1, channel:0.0.1, content:0.0.1, latest:0.0.3, searxng:0.0.1, telegram:0.0.1\n\nVersion history:\n\nv0.0.3 | 2026-02-23T13:00:09.332Z | user\n\ntg-channel-manager 0.0.3\n\n- Major refactor: new command-line tool `tgcm.py`, replacing previous interface.\n- Full CLI defined: standardized commands for channel management, token/env setup, and index rebuilding.\n- New startup preflight check for required tokens, env, and channels with automatic issue reporting and fixes.\n- Configuration is now persistent via `tgcm/.config.json`.\n- Added sample and startup files: channels config example and helper scripts.\n- Old README.md removed, documentation migrated to SKILL.md and improved with step-by-step usage and strict DOs/DON'Ts.\n\nv0.0.2 | 2026-02-21T16:47:02.027Z | user\n\nTranslate all files to English, remove Cyrillic, rename from tg-content-manager\n\nv0.0.1 | 2026-02-21T16:32:00.621Z | user\n\nInitial release: universal config-driven content pipeline for Telegram channels.\n\n  - Scout cron: finds news via SearXNG, writes drafts to content-queue.md\n  - Publisher cron: publishes approved posts to Telegram channel\n  - Dedup engine: keyword + link matching against content-index.json\n  - All channel specifics (queries, rubrics, style, filters) in openclaw.json config\n  - Zero hardcoded values — one skill for any channel\n\nArchive index:\n\nArchive v0.0.3: 9 files, 19316 bytes\n\nFiles: references/channels.example.json (130b), references/cron-setup.md (928b), references/publisher-prompt.md (1452b), references/scout-prompt.md (1894b), scripts/dedup-check.py (8575b), scripts/start-searxng.sh (878b), scripts/tgcm.py (35989b), SKILL.md (8944b), _meta.json (137b)\n\nFile v0.0.3:SKILL.md\n\n---\nname: tg-channel-manager\ndescription: |\n  Universal config-driven content pipeline engine for any Telegram channel:\n  news search via SearXNG, drafts, scheduled publishing, deduplication.\n  All channel specifics are defined in config — one skill for any channel.\nmetadata:\n  openclaw:\n    emoji: \"📡\"\n    requires:\n      bins: [\"python3\", \"curl\"]\n      env: [\"SEARXNG_URL\"]\n    primaryEnv: \"SEARXNG_URL\"\n---\n\n# TG Channel Manager\n\nPipeline: **scout → draft → human approves → publisher**.\n\n## Execution\n\n`python3` and `curl` are available in your environment (declared in `requires.bins`). Run all commands yourself using `exec`/`bash` tool. NEVER ask the user to run commands for you.\n\n## Startup\n\nWhen you load this skill, run the preflight check FIRST:\n\n```bash\npython3 {baseDir}/scripts/tgcm.py --workspace {workspace} check\n```\n\n**After check — act on results, don't ask:**\n- All `[ok]` → proceed with the user's task silently\n- `[fail] Bot token` → ask the user for the token, then save it: `tgcm.py config set bot-token <token>`. Do NOT ask where the token is or offer choices\n- `[warn] SEARXNG_URL` → ask the user for the URL, then save it: `tgcm.py config set searxng-url <url>`. Proceed without it — scout won't work but other commands will\n- `[fail] Channel` → report which channel failed and why, include the fix from the output\n- `[warn] No channels` → mention it, but proceed — the user may want to init one\n\nSettings saved via `config set` persist in `tgcm/.config.json` and are used by all subsequent commands.\n\nNEVER ask follow-up questions about check results. Report what's wrong and the fix from the output.\nIf the user hasn't specified a task — just report the check status, nothing else.\n\n## CLI Reference (FULL list — NO other commands exist)\n\nAll commands: `python3 {baseDir}/scripts/tgcm.py --workspace {workspace} <cmd>`\n\n| Command | What it does |\n|---------|-------------|\n| `init <name>` | Create a channel |\n| `list` | Show all channels |\n| `bind <name> --channel-id ID` | Bind channel to Telegram |\n| `info <name> [--chat] [--subscribers] [--permissions] [--admins] [--all]` | Channel status |\n| `get-id <@username\\|ID>` | Resolve @username or numeric ID → full channel info (id, type, title) |\n| `check` | Preflight: verify bot token, channels, env vars |\n| `config set <key> <value>` | Save setting locally (keys: bot-token, searxng-url) |\n| `config get <key>` | Read a saved setting |\n| `config list` | Show all saved settings |\n| `fetch-posts <name> [--limit N] [--dry-run]` | Load channel posts into dedup index (requires public channel with @username) |\n| `connect --channel-id ID [--channel-title T]` | Handle #tgcm connect event |\n\nBot token is auto-resolved: `--bot-token` arg → `$BOT_TOKEN` env → `openclaw.json` (auto-search) → `tgcm/.config.json`. Just call `tgcm.py get-id @username` without `--bot-token` — the script finds the token itself. If auto-detection fails, save it once: `tgcm.py config set bot-token <token>`.\n\nChannel name validation: `^[a-z0-9][a-z0-9_-]{0,62}$`.\n\n## Quick Reference\n\n| User says | Do this |\n|-----------|---------|\n| «узнай/определи channel-id» | `tgcm.py get-id @username` |\n| «подключи канал» | Recipe: Connect a channel (ниже) |\n| «какие каналы / список» | `tgcm.py list` |\n| «статус канала X» | `tgcm.py info X` |\n| «что в очереди» | `cat tgcm/<name>/content-queue.md` |\n| «загрузи посты / rebuild index» | `tgcm.py fetch-posts <name>` |\n\n## Recipes\n\n### Look up channel ID\n\n`python3 {baseDir}/scripts/tgcm.py get-id @username`\n\nToken is found automatically. Returns channel id, type, and title.\n\n### Connect a channel\n\n1. Get ID: `python3 {baseDir}/scripts/tgcm.py get-id @username`\n2. `python3 {baseDir}/scripts/tgcm.py --workspace {workspace} init <name>`\n3. `python3 {baseDir}/scripts/tgcm.py --workspace {workspace} bind <name> --channel-id <id>`\n4. Configure `skills.entries[\"tg-channel-manager\"].config` in openclaw.json\n5. Add crons (see `{baseDir}/references/cron-setup.md`)\n\n### Load channel posts (rebuild dedup index)\n\n`python3 {baseDir}/scripts/tgcm.py --workspace {workspace} fetch-posts <name>`\n\nFetches posts from the channel's public page (t.me/s/) and adds them to content-index.json.\nOptions: `--limit N` (max pages, default 5), `--dry-run` (preview only).\nRequires: channel must be public (have a @username).\n\n### View channels / status\n\n- `tgcm.py list`\n- `tgcm.py info <name>`\n- Queue: `cat tgcm/<name>/content-queue.md`\n\n## Do NOT\n\n- Invent commands — the table above is the FULL list\n- Publish posts directly — only cron Publisher does this\n- Change draft → pending — only the human does this\n- Skip dedup-check before drafting\n- Ask the user to run commands — python3 and curl are available, use exec/bash yourself\n- Ask the user for bot token or env vars — token is auto-resolved, `check` shows what's wrong\n- Ask the user follow-up questions after `check` — report errors and the fix commands, don't offer choices\n- Ask whether it's a channel or group — `get-id` returns the `type` field, this skill is for channels only\n\n## Data Layout\n\n```\ntgcm/\n  channels.json            <- [{\"name\", \"channelId\", \"status\", \"createdAt\"}, ...]\n  {channel-name}/\n    channel.json           <- per-channel metadata\n    content-index.json     <- dedup index\n    content-queue.md       <- post queue\n```\n\nA channel is bound when `channelId` is set and `status` is `\"connected\"`.\n\n## Configuration\n\nParameters are read from `openclaw.json` → `skills.entries[\"tg-channel-manager\"]`:\n\n### Telegram\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `config.channelId` | string | Telegram channel ID for publishing |\n| `config.chatId` | string | Channel community chat ID (optional) |\n\n### Limits & Schedule\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `config.maxPostsPerDay` | number | Maximum posts per day |\n| `config.maxDraftsPerRun` | number | Maximum drafts per scout run |\n| `config.timezone` | string | Schedule timezone (IANA format) |\n| `config.language` | string | Post language (ru, en, ...) |\n| `config.cronScoutTimes` | string[] | Scout schedules (cron format) |\n| `config.cronPublisherTimes` | string[] | Publisher schedules (cron format) |\n\n### Content\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `config.rubrics` | array | Rubrics: `[{id, emoji, name}, ...]` |\n| `config.searchQueries` | string[] | Search queries for SearXNG |\n| `config.searchInclude` | string | What to look for (filter description) |\n| `config.searchExclude` | string | What to discard (filter description) |\n| `config.evergreen` | string[] | Topics for articles when there are no news |\n\n### Post Style\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `config.postStyle.minChars` | number | Minimum characters per post |\n| `config.postStyle.maxChars` | number | Maximum characters per post |\n| `config.postStyle.emojiTitle` | boolean | Emoji before the title |\n| `config.postStyle.boldTitle` | boolean | Bold title |\n| `config.postStyle.signature` | string | Post signature |\n| `config.postStyle.newsFooter` | string | Extra text for news posts (empty = none) |\n| `config.postStyle.articleFooter` | string | Extra text for articles (empty = none) |\n\n### Environment\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `env.SEARXNG_URL` | string | SearXNG instance URL |\n\n### Path Resolution\n\n| Variable | How to resolve |\n|----------|---------------|\n| `{workspace}` | Your CWD. Run `pwd` or use `--workspace .` |\n| `{baseDir}` | `{workspace}/skills/tg-channel-manager` |\n\nIn sandbox mode (`workspaceAccess: \"none\"`), the workspace is under `~/.openclaw/sandboxes`, not `~/.openclaw/workspace`. Always use CWD-relative paths.\n\nCron setup: see `{baseDir}/references/cron-setup.md`.\n\n## Queue Format\n\n### Entry Format in content-queue.md\n\n```markdown\n### <number>\n- **Status:** draft | pending\n- **Rubric:** <emoji> <name> (from config.rubrics)\n- **Topic:** <topic>\n- **Source:** <url> (for news)\n- **Text:**\n\n<post text>\n```\n\nStatuses:\n- **draft** — awaiting approval\n- **pending** — approved, ready for publishing\n\nAfter publishing, the entry is **removed** from content-queue.md.\n\n## Deduplication\n\n**Before every draft** — mandatory check:\n\n```bash\npython3 {baseDir}/scripts/dedup-check.py --base-dir <workspace> --topic \"topic\" --links \"url1\" \"url2\"\n```\n\n**After publishing** — add to index:\n\n```bash\npython3 {baseDir}/scripts/dedup-check.py --base-dir <workspace> --add <msgId> --topic \"topic\" --links \"url\"\n```\n\n**Rebuild index** (via Telegram search):\n\n```bash\npython3 {baseDir}/scripts/dedup-check.py --base-dir <workspace> --rebuild --channel-id <config.channelId>\n```\n\nIndex is stored in `<workspace>/content-index.json` (or per-channel: `tgcm/<name>/content-index.json`).\n\nFile v0.0.3:_meta.json\n\n{\n  \"ownerId\": \"kn78whtxvy1hj3yfytx3542z9981kymk\",\n  \"slug\": \"tg-channel-manager\",\n  \"version\": \"0.0.3\",\n  \"publishedAt\": 1771851609332\n}\n\nFile v0.0.3:references/channels.example.json\n\n[\n  {\n    \"name\": \"my-channel\",\n    \"channelId\": null,\n    \"status\": \"initialized\",\n    \"createdAt\": \"2025-01-01T00:00:00Z\"\n  }\n]\n\nFile v0.0.3:references/cron-setup.md\n\n# Cron Setup for Content System\n\nAll parameters come from `openclaw.json` → `skills.entries[\"tg-channel-manager\"].config`.\n\n## News Scout\n\nSearches for news and writes drafts to content-queue.md.\n\n```bash\n# For each time from config.cronScoutTimes:\nopenclaw cron add \\\n  --name \"content-scout-<N>\" \\\n  --schedule \"<config.cronScoutTimes[N]>\" \\\n  --timezone \"<config.timezone>\" \\\n  --prompt-file \"{baseDir}/references/scout-prompt.md\"\n```\n\n## Publisher\n\nTakes pending posts and publishes them to the channel.\n\n```bash\n# For each time from config.cronPublisherTimes:\nopenclaw cron add \\\n  --name \"content-pub-<N>\" \\\n  --schedule \"<config.cronPublisherTimes[N]>\" \\\n  --timezone \"<config.timezone>\" \\\n  --prompt-file \"{baseDir}/references/publisher-prompt.md\"\n```\n\n## Management\n\n```bash\n# List crons\nopenclaw cron list\n\n# Remove a cron\nopenclaw cron remove --name \"content-scout-1\"\n\n# Check next trigger\nopenclaw cron status\n```\n\nFile v0.0.3:references/publisher-prompt.md\n\n# Cron: Publisher\n\nRead {baseDir}/SKILL.md — it contains full content system documentation.\nRead the `tg-channel-manager` skill config from openclaw.json.\n\n## Task\n\nPublish one pending post from content-queue.md to the Telegram channel.\n\n## Steps\n\n1. Read content-queue.md\n2. Find posts with **pending** status\n3. If there are no pending posts — **DO NOTHING**. Do not generate content yourself.\n4. Check how many posts have already been published TODAY (via `message tool action=search`). If `config.maxPostsPerDay` or more — do not publish.\n5. Pick one post. **Alternate rubrics** when possible: check the last published post — if its rubric matches the current one, pick a post with a different rubric (if available in pending).\n6. Append the signature to the post text: `config.postStyle.signature`\n7. For news, add `config.postStyle.newsFooter` (if not empty)\n8. For articles, add `config.postStyle.articleFooter` (if not empty)\n9. Publish via:\n   ```\n   message tool (action=send, channel=telegram, target=<config.channelId>, text=\"post text\")\n   ```\n10. **Remove** the published entry from content-queue.md\n11. Add to the dedup index:\n    ```bash\n    python3 {baseDir}/scripts/dedup-check.py --base-dir . --add <msgId> --topic \"topic\" --links \"url\"\n    ```\n\n## Rules\n\n- Maximum 1 post per run\n- Maximum `config.maxPostsPerDay` posts per day\n- DO NOT generate content yourself — only publish pending posts\n- Language: `config.language`\n\nFile v0.0.3:references/scout-prompt.md\n\n# Cron: Content Scout\n\nRead {baseDir}/SKILL.md — it contains full content system documentation.\nRead the `tg-channel-manager` skill config from openclaw.json.\n\n## Task\n\nFind fresh news and write drafts to content-queue.md.\n\n## Steps\n\n### 1. Search for news\n\nFor each query from `config.searchQueries`, run:\n\n```bash\ncurl '$SEARXNG_URL/search?q=<query (URL-encoded)>&format=json&time_range=day&language=en'\n```\n\n### 2. Filtering\n\n- ONLY news from the last 24 hours\n- INCLUDE: `config.searchInclude`\n- EXCLUDE: `config.searchExclude`\n\n### 3. Decision\n\n- Found fresh interesting news → write a news draft (step 4A)\n- Did NOT find news → write an evergreen article draft (step 4B)\n\n### 4A. News Draft\n\n1. Read content-queue.md — do not duplicate topics\n2. **MANDATORY** dedup check:\n   ```bash\n   python3 {baseDir}/scripts/dedup-check.py --base-dir . --topic \"topic\" --links \"url1\" \"url2\"\n   ```\n   If matches found — DO NOT create a draft, move to the next news item.\n3. **MANDATORY** open the source and read its content. Do not write a post from a headline alone!\n4. Write a draft following the format from SKILL.md, style per `config.postStyle`\n5. Pick a rubric from `config.rubrics` — choose the most fitting one\n\n### 4B. Evergreen Article (if no news found)\n\n1. Read `config.evergreen` — pick a topic\n2. Find and read documentation/sources on the topic\n3. Write a draft — detailed, in plain language\n4. Style per `config.postStyle`, add `articleFooter` if set\n5. Pick a rubric from `config.rubrics` — choose the most fitting one\n\n### 5. Write to Queue\n\nAdd the draft to content-queue.md with **draft** status (NOT pending!).\n\n## Rules\n\n- Maximum `config.maxDraftsPerRun` drafts per run\n- DO NOT PUBLISH anything. Only write drafts to the file\n- Do not duplicate existing draft/pending topics\n- BEFORE creating — MANDATORY dedup-check.py\n- Post language: `config.language`\n\nArchive v0.0.2: 7 files, 8834 bytes\n\nFiles: README.md (1487b), references/cron-setup.md (928b), references/publisher-prompt.md (1452b), references/scout-prompt.md (1894b), scripts/dedup-check.py (7298b), SKILL.md (6040b), _meta.json (137b)\n\nFile v0.0.2:SKILL.md\n\n---\nname: tg-channel-manager\ndescription: |\n  Universal config-driven content pipeline engine for any Telegram channel:\n  news search via SearXNG, drafts, scheduled publishing, deduplication.\n  All channel specifics are defined in config — one skill for any channel.\nmetadata:\n  openclaw:\n    emoji: \"📡\"\n    requires:\n      bins: [\"python3\", \"curl\"]\n      env: [\"SEARXNG_URL\"]\n    primaryEnv: \"SEARXNG_URL\"\n---\n\n# TG Channel Manager\n\nUniversal content engine for any Telegram channel.\nPipeline: **scout → draft → human approves → publisher**.\n\nAll specifics (topics, rubrics, style, filters) are defined in config — the skill contains zero hardcoded values.\n\n## Configuration\n\nParameters are read from `openclaw.json` → `skills.entries[\"tg-channel-manager\"]`:\n\n### Telegram\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `config.channelId` | string | Telegram channel ID for publishing |\n| `config.chatId` | string | Channel community chat ID (optional) |\n\n### Limits & Schedule\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `config.maxPostsPerDay` | number | Maximum posts per day |\n| `config.maxDraftsPerRun` | number | Maximum drafts per scout run |\n| `config.timezone` | string | Schedule timezone (IANA format) |\n| `config.language` | string | Post language (ru, en, ...) |\n| `config.cronScoutTimes` | string[] | Scout schedules (cron format) |\n| `config.cronPublisherTimes` | string[] | Publisher schedules (cron format) |\n\n### Content\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `config.rubrics` | array | Rubrics: `[{id, emoji, name}, ...]` |\n| `config.searchQueries` | string[] | Search queries for SearXNG |\n| `config.searchInclude` | string | What to look for (filter description) |\n| `config.searchExclude` | string | What to discard (filter description) |\n| `config.evergreen` | string[] | Topics for articles when there are no news |\n\n### Post Style\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `config.postStyle.minChars` | number | Minimum characters per post |\n| `config.postStyle.maxChars` | number | Maximum characters per post |\n| `config.postStyle.emojiTitle` | boolean | Emoji before the title |\n| `config.postStyle.boldTitle` | boolean | Bold title |\n| `config.postStyle.signature` | string | Post signature |\n| `config.postStyle.newsFooter` | string | Extra text for news posts (empty = none) |\n| `config.postStyle.articleFooter` | string | Extra text for articles (empty = none) |\n\n### Environment\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `env.SEARXNG_URL` | string | SearXNG instance URL |\n\n`{baseDir}` — path to the skill folder (where this file resides).\n\n## Runtime Files\n\n- **`content-queue.md`** — post queue (draft / pending). Located in the agent's workspace, NOT in the skill folder.\n- **`content-index.json`** — deduplication index. Located in the agent's workspace.\n\n### Entry Format in content-queue.md\n\n```markdown\n### <number>\n- **Status:** draft | pending\n- **Rubric:** <emoji> <name> (from config.rubrics)\n- **Topic:** <topic>\n- **Source:** <url> (for news)\n- **Text:**\n\n<post text>\n```\n\nStatuses:\n- **draft** — draft, awaiting approval\n- **pending** — approved, ready for publishing\n\nAfter publishing, the entry is **removed** from content-queue.md.\n\n## Pipeline\n\n### 1. Scout (cron)\n\nPrompt: `{baseDir}/references/scout-prompt.md`\n\n1. Executes search queries from `config.searchQueries` via `$SEARXNG_URL`\n2. Filters by `config.searchInclude` / `config.searchExclude`\n3. Checks for duplicates via dedup-check.py\n4. Writes a draft to content-queue.md with **draft** status\n5. Maximum `config.maxDraftsPerRun` drafts per run\n6. If no news found — picks a topic from `config.evergreen`\n\n### 2. Approval (human)\n\nHuman reviews draft → changes status to **pending**.\n\n### 3. Publisher (cron)\n\nPrompt: `{baseDir}/references/publisher-prompt.md`\n\n1. Reads content-queue.md\n2. Takes the first **pending** post\n3. Alternates rubrics when possible\n4. Appends signature from `config.postStyle.signature`\n5. Publishes via `message tool (action=send, channel=telegram, target=<config.channelId>)`\n6. Removes the entry from content-queue.md\n7. Adds to dedup index\n8. Maximum 1 post per run, `config.maxPostsPerDay` per day\n\n## Telegram API\n\n### Check published posts\n```\nmessage tool (action=search, channel=telegram, target=<config.channelId>, query=\"keywords\")\n```\n\n### Publish a post\n```\nmessage tool (action=send, channel=telegram, target=<config.channelId>, text=\"post text\")\n```\n\n## Deduplication\n\n**Before every draft** — mandatory check:\n\n```bash\npython3 {baseDir}/scripts/dedup-check.py --base-dir <workspace> --topic \"topic\" --links \"url1\" \"url2\"\n```\n\n**After publishing** — add to index:\n\n```bash\npython3 {baseDir}/scripts/dedup-check.py --base-dir <workspace> --add <msgId> --topic \"topic\" --links \"url\"\n```\n\n**Rebuild index** (via Telegram search):\n\n```bash\npython3 {baseDir}/scripts/dedup-check.py --base-dir <workspace> --rebuild --channel-id <config.channelId>\n```\n\nIndex is stored in `<workspace>/content-index.json`.\n\n## SearXNG — News Search\n\nFor each query from `config.searchQueries`:\n\n```bash\ncurl '$SEARXNG_URL/search?q=<query>&format=json&time_range=day&language=en'\n```\n\n## Post Format\n\nDefined by `config.postStyle` parameters:\n\n- Title: emoji (if `emojiTitle`) + bold (if `boldTitle`)\n- Length: from `minChars` to `maxChars` characters\n- Language: from `config.language`\n- Signature: `config.postStyle.signature`\n- For news: link to original source + `newsFooter` (if not empty)\n- For articles: `articleFooter` (if not empty)\n- Prefer primary sources (specs, GitHub, official blogs) over summaries\n- All links https://\n- NO personal data\n\n## Rubrics\n\nRubrics are defined in `config.rubrics`. Each rubric: `{id, emoji, name}`.\n\nScout picks the appropriate rubric from the list when creating a draft.\n\n## Initial Cron Setup\n\nSee `{baseDir}/references/cron-setup.md` — `openclaw cron add` command templates.\n\nFile v0.0.2:README.md\n\n# tg-channel-manager\n\nUniversal config-driven content pipeline for any Telegram channel. An [OpenClaw](https://openclaw.dev) skill package.\n\n## What it does\n\nOne skill, any channel — all specifics (topics, rubrics, style, filters) live in `openclaw.json` config, not in code.\n\n**Pipeline:** Scout (cron) → Draft → Human approval → Publisher (cron) → Telegram channel\n\n- **Scout** searches for news via SearXNG, filters duplicates, writes drafts\n- **Human** reviews drafts, approves by changing status to `pending`\n- **Publisher** picks pending posts, formats, publishes to Telegram, updates dedup index\n\n## Features\n\n- Config-driven: channel ID, rubrics, post style, schedules — all in config\n- Deduplication via keyword matching and link checking\n- SearXNG integration for news discovery\n- Evergreen content fallback when no fresh news\n- Rubric rotation for content variety\n\n## Structure\n\n```\n├── SKILL.md                    # Skill documentation & config reference\n├── scripts/\n│   └── dedup-check.py          # Content deduplication tool\n└── references/\n    ├── cron-setup.md           # Cron setup templates\n    ├── scout-prompt.md         # Scout cron prompt\n    └── publisher-prompt.md     # Publisher cron prompt\n```\n\n## Requirements\n\n- Python 3\n- curl\n- SearXNG instance (set `SEARXNG_URL` env var)\n\n## Usage\n\nSee [SKILL.md](SKILL.md) for full documentation, configuration reference, and pipeline details.\n\n## License\n\nMIT\n\nFile v0.0.2:_meta.json\n\n{\n  \"ownerId\": \"kn78whtxvy1hj3yfytx3542z9981kymk\",\n  \"slug\": \"tg-channel-manager\",\n  \"version\": \"0.0.2\",\n  \"publishedAt\": 1771692422027\n}\n\nFile v0.0.2:references/cron-setup.md\n\n# Cron Setup for Content System\n\nAll parameters come from `openclaw.json` → `skills.entries[\"tg-channel-manager\"].config`.\n\n## News Scout\n\nSearches for news and writes drafts to content-queue.md.\n\n```bash\n# For each time from config.cronScoutTimes:\nopenclaw cron add \\\n  --name \"content-scout-<N>\" \\\n  --schedule \"<config.cronScoutTimes[N]>\" \\\n  --timezone \"<config.timezone>\" \\\n  --prompt-file \"{baseDir}/references/scout-prompt.md\"\n```\n\n## Publisher\n\nTakes pending posts and publishes them to the channel.\n\n```bash\n# For each time from config.cronPublisherTimes:\nopenclaw cron add \\\n  --name \"content-pub-<N>\" \\\n  --schedule \"<config.cronPublisherTimes[N]>\" \\\n  --timezone \"<config.timezone>\" \\\n  --prompt-file \"{baseDir}/references/publisher-prompt.md\"\n```\n\n## Management\n\n```bash\n# List crons\nopenclaw cron list\n\n# Remove a cron\nopenclaw cron remove --name \"content-scout-1\"\n\n# Check next trigger\nopenclaw cron status\n```\n\nFile v0.0.2:references/publisher-prompt.md\n\n# Cron: Publisher\n\nRead {baseDir}/SKILL.md — it contains full content system documentation.\nRead the `tg-channel-manager` skill config from openclaw.json.\n\n## Task\n\nPublish one pending post from content-queue.md to the Telegram channel.\n\n## Steps\n\n1. Read content-queue.md\n2. Find posts with **pending** status\n3. If there are no pending posts — **DO NOTHING**. Do not generate content yourself.\n4. Check how many posts have already been published TODAY (via `message tool action=search`). If `config.maxPostsPerDay` or more — do not publish.\n5. Pick one post. **Alternate rubrics** when possible: check the last published post — if its rubric matches the current one, pick a post with a different rubric (if available in pending).\n6. Append the signature to the post text: `config.postStyle.signature`\n7. For news, add `config.postStyle.newsFooter` (if not empty)\n8. For articles, add `config.postStyle.articleFooter` (if not empty)\n9. Publish via:\n   ```\n   message tool (action=send, channel=telegram, target=<config.channelId>, text=\"post text\")\n   ```\n10. **Remove** the published entry from content-queue.md\n11. Add to the dedup index:\n    ```bash\n    python3 {baseDir}/scripts/dedup-check.py --base-dir . --add <msgId> --topic \"topic\" --links \"url\"\n    ```\n\n## Rules\n\n- Maximum 1 post per run\n- Maximum `config.maxPostsPerDay` posts per day\n- DO NOT generate content yourself — only publish pending posts\n- Language: `config.language`\n\nFile v0.0.2:references/scout-prompt.md\n\n# Cron: Content Scout\n\nRead {baseDir}/SKILL.md — it contains full content system documentation.\nRead the `tg-channel-manager` skill config from openclaw.json.\n\n## Task\n\nFind fresh news and write drafts to content-queue.md.\n\n## Steps\n\n### 1. Search for news\n\nFor each query from `config.searchQueries`, run:\n\n```bash\ncurl '$SEARXNG_URL/search?q=<query (URL-encoded)>&format=json&time_range=day&language=en'\n```\n\n### 2. Filtering\n\n- ONLY news from the last 24 hours\n- INCLUDE: `config.searchInclude`\n- EXCLUDE: `config.searchExclude`\n\n### 3. Decision\n\n- Found fresh interesting news → write a news draft (step 4A)\n- Did NOT find news → write an evergreen article draft (step 4B)\n\n### 4A. News Draft\n\n1. Read content-queue.md — do not duplicate topics\n2. **MANDATORY** dedup check:\n   ```bash\n   python3 {baseDir}/scripts/dedup-check.py --base-dir . --topic \"topic\" --links \"url1\" \"url2\"\n   ```\n   If matches found — DO NOT create a draft, move to the next news item.\n3. **MANDATORY** open the source and read its content. Do not write a post from a headline alone!\n4. Write a draft following the format from SKILL.md, style per `config.postStyle`\n5. Pick a rubric from `config.rubrics` — choose the most fitting one\n\n### 4B. Evergreen Article (if no news found)\n\n1. Read `config.evergreen` — pick a topic\n2. Find and read documentation/sources on the topic\n3. Write a draft — detailed, in plain language\n4. Style per `config.postStyle`, add `articleFooter` if set\n5. Pick a rubric from `config.rubrics` — choose the most fitting one\n\n### 5. Write to Queue\n\nAdd the draft to content-queue.md with **draft** status (NOT pending!).\n\n## Rules\n\n- Maximum `config.maxDraftsPerRun` drafts per run\n- DO NOT PUBLISH anything. Only write drafts to the file\n- Do not duplicate existing draft/pending topics\n- BEFORE creating — MANDATORY dedup-check.py\n- Post language: `config.language`\n\nArchive v0.0.1: 6 files, 9705 bytes\n\nFiles: references/cron-setup.md (1182b), references/publisher-prompt.md (2118b), references/scout-prompt.md (2846b), scripts/dedup-check.py (8443b), SKILL.md (8259b), _meta.json (137b)\n\nFile v0.0.1:SKILL.md\n\n---\nname: tg-content-manager\ndescription: |\n  Универсальный движок контент-пайплайна для Telegram-канала:\n  поиск новостей через SearXNG, черновики, публикация по расписанию, дедупликация.\n  Вся специфика канала задаётся в config — один скилл для любого канала.\nmetadata:\n  openclaw:\n    emoji: \"📡\"\n    requires:\n      bins: [\"python3\", \"curl\"]\n      env: [\"SEARXNG_URL\"]\n    primaryEnv: \"SEARXNG_URL\"\n---\n\n# TG Content Manager\n\nУниверсальный контент-движок для Telegram-канала.\nПайплайн: **разведчик → draft → человек одобряет → публикатор**.\n\nВся специфика (темы, рубрики, стиль, фильтры) задаётся в config — скилл не содержит hardcoded значений.\n\n## Конфигурация\n\nПараметры читаются из `openclaw.json` → `skills.entries[\"tg-content-manager\"]`:\n\n### Telegram\n\n| Параметр | Тип | Описание |\n|----------|-----|----------|\n| `config.channelId` | string | ID Telegram-канала для публикации |\n| `config.chatId` | string | ID чата канала (комьюнити), опционально |\n\n### Лимиты и расписание\n\n| Параметр | Тип | Описание |\n|----------|-----|----------|\n| `config.maxPostsPerDay` | number | Максимум постов в день |\n| `config.maxDraftsPerRun` | number | Максимум черновиков за один заход разведчика |\n| `config.timezone` | string | Часовой пояс расписания (IANA формат) |\n| `config.language` | string | Язык постов (ru, en, ...) |\n| `config.cronScoutTimes` | string[] | Расписания разведчика (cron-формат) |\n| `config.cronPublisherTimes` | string[] | Расписания публикатора (cron-формат) |\n\n### Контент\n\n| Параметр | Тип | Описание |\n|----------|-----|----------|\n| `config.rubrics` | array | Рубрики: `[{id, emoji, name}, ...]` |\n| `config.searchQueries` | string[] | Поисковые запросы для SearXNG |\n| `config.searchInclude` | string | Что искать (описание для фильтрации) |\n| `config.searchExclude` | string | Что отбрасывать (описание для фильтрации) |\n| `config.evergreen` | string[] | Темы для статей, когда нет новостей |\n\n### Стиль постов\n\n| Параметр | Тип | Описание |\n|----------|-----|----------|\n| `config.postStyle.minChars` | number | Минимум символов в посте |\n| `config.postStyle.maxChars` | number | Максимум символов в посте |\n| `config.postStyle.emojiTitle` | boolean | Эмодзи перед заголовком |\n| `config.postStyle.boldTitle` | boolean | Жирный заголовок |\n| `config.postStyle.signature` | string | Подпись в конце поста |\n| `config.postStyle.newsFooter` | string | Доп. текст для новостей (пусто = ничего) |\n| `config.postStyle.articleFooter` | string | Доп. текст для статей (пусто = ничего) |\n\n### Окружение\n\n| Параметр | Тип | Описание |\n|----------|-----|----------|\n| `env.SEARXNG_URL` | string | URL SearXNG-инстанса |\n\n`{baseDir}` — путь к папке скилла (где лежит этот файл).\n\n## Рабочие файлы\n\n- **`content-queue.md`** — очередь постов (draft / pending). Лежит в workspace агента, НЕ в папке скилла.\n- **`content-index.json`** — индекс дедупликации. Лежит в workspace агента.\n\n### Формат записи в content-queue.md\n\n```markdown\n### <номер>\n- **Статус:** draft | pending\n- **Рубрика:** <emoji> <name> (из config.rubrics)\n- **Тема:** <тема>\n- **Источник:** <url> (для новостей)\n- **Текст:**\n\n<текст поста>\n```\n\nСтатусы:\n- **draft** — черновик, ждёт одобрения\n- **pending** — одобрен, готов к публикации\n\nПосле публикации запись **удаляется** из content-queue.md.\n\n## Пайплайн\n\n### 1. Разведчик (крон)\n\nПромпт: `{baseDir}/references/scout-prompt.md`\n\n1. Выполняет поисковые запросы из `config.searchQueries` через `$SEARXNG_URL`\n2. Фильтрует по `config.searchInclude` / `config.searchExclude`\n3. Проверяет дубли через dedup-check.py\n4. Пишет черновик в content-queue.md со статусом **draft**\n5. Максимум `config.maxDraftsPerRun` черновиков за заход\n6. Если новостей нет — берёт тему из `config.evergreen`\n\n### 2. Одобрение (человек)\n\nЧеловек читает draft → меняет статус на **pending**.\n\n### 3. Публикатор (крон)\n\nПромпт: `{baseDir}/references/publisher-prompt.md`\n\n1. Читает content-queue.md\n2. Берёт первый **pending** пост\n3. Чередует рубрики (по возможности)\n4. Добавляет подпись из `config.postStyle.signature`\n5. Публикует через `message tool (action=send, channel=telegram, target=<config.channelId>)`\n6. Удаляет запись из content-queue.md\n7. Добавляет в dedup-индекс\n8. Максимум 1 пост за заход, `config.maxPostsPerDay` в день\n\n## Telegram API\n\n### Проверить опубликованное\n```\nmessage tool (action=search, channel=telegram, target=<config.channelId>, query=\"ключевые слова\")\n```\n\n### Опубликовать пост\n```\nmessage tool (action=send, channel=telegram, target=<config.channelId>, text=\"текст поста\")\n```\n\n## Дедупликация\n\n**Перед каждым черновиком** — обязательная проверка:\n\n```bash\npython3 {baseDir}/scripts/dedup-check.py --base-dir <workspace> --topic \"тема\" --links \"url1\" \"url2\"\n```\n\n**После публикации** — добавление в индекс:\n\n```bash\npython3 {baseDir}/scripts/dedup-check.py --base-dir <workspace> --add <msgId> --topic \"тема\" --links \"url\"\n```\n\n**Пересборка индекса** (через Telegram search):\n\n```bash\npython3 {baseDir}/scripts/dedup-check.py --base-dir <workspace> --rebuild --channel-id <config.channelId>\n```\n\nИндекс хранится в `<workspace>/content-index.json`.\n\n## SearXNG — поиск новостей\n\nДля каждого запроса из `config.searchQueries`:\n\n```bash\ncurl '$SEARXNG_URL/search?q=<query>&format=json&time_range=day&language=en'\n```\n\n## Формат постов\n\nОпределяется параметрами `config.postStyle`:\n\n- Заголовок: эмодзи (если `emojiTitle`) + жирный (если `boldTitle`)\n- Длина: от `minChars` до `maxChars` символов\n- Язык: из `config.language`\n- Подпись: `config.postStyle.signature`\n- Для новостей: ссылка на первоисточник + `newsFooter` (если не пуст)\n- Для статей: `articleFooter` (если не пуст)\n- Предпочитать первоисточники (спецификации, GitHub, офиц. блоги) перед пересказами\n- Все ссылки https://\n- БЕЗ личных данных\n\n## Рубрики\n\nРубрики задаются в `config.rubrics`. Каждая рубрика: `{id, emoji, name}`.\n\nРазведчик выбирает подходящую рубрику из списка при создании черновика.\n\n## Первоначальная настройка кронов\n\nСм. `{baseDir}/references/cron-setup.md` — шаблоны команд `openclaw cron add`.\n\nFile v0.0.1:_meta.json\n\n{\n  \"ownerId\": \"kn78whtxvy1hj3yfytx3542z9981kymk\",\n  \"slug\": \"tg-channel-manager\",\n  \"version\": \"0.0.1\",\n  \"publishedAt\": 1771691520621\n}\n\nFile v0.0.1:references/cron-setup.md\n\n# Настройка кронов для контент-системы\n\nВсе параметры берутся из `openclaw.json` → `skills.entries[\"tg-content-manager\"].config`.\n\n## Разведчик новостей\n\nИщет новости и пишет черновики в content-queue.md.\n\n```bash\n# Для каждого времени из config.cronScoutTimes:\nopenclaw cron add \\\n  --name \"content-scout-<N>\" \\\n  --schedule \"<config.cronScoutTimes[N]>\" \\\n  --timezone \"<config.timezone>\" \\\n  --prompt-file \"{baseDir}/references/scout-prompt.md\"\n```\n\n## Публикатор\n\nБерёт pending посты и публикует в канал.\n\n```bash\n# Для каждого времени из config.cronPublisherTimes:\nopenclaw cron add \\\n  --name \"content-pub-<N>\" \\\n  --schedule \"<config.cronPublisherTimes[N]>\" \\\n  --timezone \"<config.timezone>\" \\\n  --prompt-file \"{baseDir}/references/publisher-prompt.md\"\n```\n\n## Управление\n\n```bash\n# Список кронов\nopenclaw cron list\n\n# Удалить крон\nopenclaw cron remove --name \"content-scout-1\"\n\n# Проверить следующее срабатывание\nopenclaw cron status\n```\n\nFile v0.0.1:references/publisher-prompt.md\n\n# Крон: публикатор\n\nПрочитай {baseDir}/SKILL.md — там полная документация по контент-системе.\nПрочитай config скилла `tg-content-manager` из openclaw.json.\n\n## Задача\n\nОпубликовать один pending пост из content-queue.md в Telegram-канал.\n\n## Порядок действий\n\n1. Прочитай content-queue.md\n2. Найди посты со статусом **pending**\n3. Если pending постов нет — **НЕ ДЕЛАЙ НИЧЕГО**. Не генерируй контент сам.\n4. Проверь, сколько постов уже опубликовано СЕГОДНЯ (через `message tool action=search`). Если `config.maxPostsPerDay` или больше — не публикуй.\n5. Выбери один пост. **Чередуй рубрики** по возможности: проверь последний опубликованный пост — если рубрика совпадает с текущим, выбери пост другой рубрики (если есть в pending).\n6. Добавь в конец текста поста подпись: `config.postStyle.signature`\n7. Для новостей добавь `config.postStyle.newsFooter` (если не пуст)\n8. Для статей добавь `config.postStyle.articleFooter` (если не пуст)\n9. Опубликуй через:\n   ```\n   message tool (action=send, channel=telegram, target=<config.channelId>, text=\"текст поста\")\n   ```\n10. **Удали** опубликованную запись из content-queue.md\n11. Добавь в dedup-индекс:\n    ```bash\n    python3 {baseDir}/scripts/dedup-check.py --base-dir . --add <msgId> --topic \"тема\" --links \"url\"\n    ```\n\n## Правила\n\n- Максимум 1 пост за заход\n- Максимум `config.maxPostsPerDay` постов в день\n- НЕ генерировать контент самостоятельно — только публиковать pending\n- Язык: `config.language`\n\nFile v0.0.1:references/scout-prompt.md\n\n# Крон: разведчик контента\n\nПрочитай {baseDir}/SKILL.md — там полная документация по контент-системе.\nПрочитай config скилла `tg-content-manager` из openclaw.json.\n\n## Задача\n\nНайти свежие новости и написать черновики в content-queue.md.\n\n## Порядок действий\n\n### 1. Поиск новостей\n\nДля каждого запроса из `config.searchQueries` выполни:\n\n```bash\ncurl '$SEARXNG_URL/search?q=<query (URL-encoded)>&format=json&time_range=day&language=en'\n```\n\n### 2. Фильтрация\n\n- ТОЛЬКО новости за последние 24 часа\n- НУЖНЫ: `config.searchInclude`\n- НЕ НУЖНЫ: `config.searchExclude`\n\n### 3. Решение\n\n- Нашёл свежие интересные новости → пиши черновик новости (шаг 4А)\n- НЕ нашёл новостей → пиши черновик evergreen статьи (шаг 4Б)\n\n### 4А. Черновик новости\n\n1. Прочитай content-queue.md — не дублируй темы\n2. **ОБЯЗАТЕЛЬНО** проверь на дубли:\n   ```bash\n   python3 {baseDir}/scripts/dedup-check.py --base-dir . --topic \"тема\" --links \"url1\" \"url2\"\n   ```\n   Если найдены совпадения — НЕ создавай черновик, переходи к следующей новости.\n3. **ОБЯЗАТЕЛЬНО** открой источник и прочитай содержимое. Не пиши пост по одному заголовку!\n4. Напиши черновик по формату из SKILL.md, стиль по `config.postStyle`\n5. Рубрику бери из `config.rubrics` — выбери подходящую\n\n### 4Б. Evergreen статья (если новостей нет)\n\n1. Прочитай `config.evergreen` — выбери тему\n2. Найди и прочитай документацию/источники по теме\n3. Напиши черновик — подробно, простым языком\n4. Стиль по `config.postStyle`, добавь `articleFooter` если задан\n5. Рубрику бери из `config.rubrics` — выбери подходящую\n\n### 5. Запись в очередь\n\nДобавь черновик в content-queue.md со статусом **draft** (НЕ pending!).\n\n## Правила\n\n- Максимум `config.maxDraftsPerRun` черновиков за заход\n- НЕ ПУБЛИКУЙ ничего. Только пиши черновики в файл\n- Не дублируй уже существующие draft/pending темы\n- ПЕРЕД созданием — ОБЯЗАТЕЛЬНО dedup-check.py\n- Язык постов: `config.language`","readmeExcerpt":"Skill: TG Channel Manager Owner: axisrow Summary: Universal config-driven content pipeline engine for any Telegram channel: news search via SearXNG, drafts, scheduled publishing, deduplication. All channel s... Tags: automation:0.0.1, channel:0.0.1, content:0.0.1, latest:0.0.3, searxng:0.0.1, telegram:0.0.1 Version history: v0.0.3 | 2026-02-23T13:00:09.332Z | user tg-channel-manager 0.0.3 - Major refactor: new comman","codeSnippets":[],"executableExamples":[{"language":"bash","snippet":"python3 {baseDir}/scripts/tgcm.py --workspace {workspace} check"},{"language":"text","snippet":"tgcm/\n  channels.json            <- [{\"name\", \"channelId\", \"status\", \"createdAt\"}, ...]\n  {channel-name}/\n    channel.json           <- per-channel metadata\n    content-index.json     <- dedup index\n    content-queue.md       <- post queue"},{"language":"markdown","snippet":"### <number>\n- **Status:** draft | pending\n- **Rubric:** <emoji> <name> (from config.rubrics)\n- **Topic:** <topic>\n- **Source:** <url> (for news)\n- **Text:**\n\n<post text>"},{"language":"bash","snippet":"python3 {baseDir}/scripts/dedup-check.py --base-dir <workspace> --topic \"topic\" --links \"url1\" \"url2\""},{"language":"bash","snippet":"python3 {baseDir}/scripts/dedup-check.py --base-dir <workspace> --add <msgId> --topic \"topic\" --links \"url\""},{"language":"bash","snippet":"python3 {baseDir}/scripts/dedup-check.py --base-dir <workspace> --rebuild --channel-id <config.channelId>"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: tg-channel-manager\ndescription: |\n  Universal config-driven content pipeline engine for any Telegram channel:\n  news search via SearXNG, drafts, scheduled publishing, deduplication.\n  All channel specifics are defined in config — one skill for any channel.\nmetadata:\n  openclaw:\n    emoji: \"📡\"\n    requires:\n      bins: [\"python3\", \"curl\"]\n      env: [\"SEARXNG_URL\"]\n    primaryEnv: \"SEARXNG_URL\"\n---\n\n# TG Channel Manager\n\nPipeline: **scout → draft → human approves → publisher**.\n\n## Execution\n\n`python3` and `curl` are available in your environment (declared in `requires.bins`). Run all commands yourself using `exec`/`bash` tool. NEVER ask the user to run commands for you.\n\n## Startup\n\nWhen you load this skill, run the preflight check FIRST:\n\n```bash\npython3 {baseDir}/scripts/tgcm.py --workspace {workspace} check\n```\n\n**After check — act on results, don't ask:**\n- All `[ok]` → proceed with the user's task silently\n- `[fail] Bot token` → ask the user for the token, then save it: `tgcm.py config set bot-token <token>`. Do NOT ask where the token is or offer choices\n- `[warn] SEARXNG_URL` → ask the user for the URL, then save it: `tgcm.py config set searxng-url <url>`. Proceed without it — scout won't work but other commands will\n- `[fail] Channel` → report which channel failed and why, include the fix from the output\n- `[warn] No channels` → mention it, but proceed — the user may want to init one\n\nSettings saved via `config set` persist in `tgcm/.config.json` and are used by all subsequent commands.\n\nNEVER ask follow-up questions about check results. Report what's wrong and the fix from the output.\nIf the user hasn't specified a task — just report the check status, nothing else.\n\n## CLI Reference (FULL list — NO other commands exist)\n\nAll commands: `python3 {baseDir}/scripts/tgcm.py --workspace {workspace} <cmd>`\n\n| Command | What it does |\n|---------|-------------|\n| `init <name>` | Create a channel |\n| `list` | Show all channels |\n| `bind <name> --channel-id ID` | Bind channel to Telegram |\n| `info <name> [--chat] [--subscribers] [--permissions] [--admins] [--all]` | Channel status |\n| `get-id <@username\\|ID>` | Resolve @username or numeric ID → full channel info (id, type, title) |\n| `check` | Preflight: verify bot token, channels, env vars |\n| `config set <key> <value>` | Save setting locally (keys: bot-token, searxng-url) |\n| `config get <key>` | Read a saved setting |\n| `config list` | Show all saved settings |\n| `fetch-posts <name> [--limit N] [--dry-run]` | Load channel posts into dedup index (requires public channel with @username) |\n| `connect --channel-id ID [--channel-title T]` | Handle #tgcm connect event |\n\nBot token is auto-resolved: `--bot-token` arg → `$BOT_TOKEN` env → `openclaw.json` (auto-search) → `tgcm/.config.json`. Just call `tgcm.py get-id @username` without `--bot-token` — the script finds the token itself. If auto-detection fails, save it once: `tgcm.py config set bot-token <token>`.\n\nChannel name validation: `^[a"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn78whtxvy1hj3yfytx3542z9981kymk\",\n  \"slug\": \"tg-channel-manager\",\n  \"version\": \"0.0.3\",\n  \"publishedAt\": 1771851609332\n}"},{"path":"references/channels.example.json","content":"[\n  {\n    \"name\": \"my-channel\",\n    \"channelId\": null,\n    \"status\": \"initialized\",\n    \"createdAt\": \"2025-01-01T00:00:00Z\"\n  }\n]"},{"path":"references/cron-setup.md","content":"# Cron Setup for Content System\n\nAll parameters come from `openclaw.json` → `skills.entries[\"tg-channel-manager\"].config`.\n\n## News Scout\n\nSearches for news and writes drafts to content-queue.md.\n\n```bash\n# For each time from config.cronScoutTimes:\nopenclaw cron add \\\n  --name \"content-scout-<N>\" \\\n  --schedule \"<config.cronScoutTimes[N]>\" \\\n  --timezone \"<config.timezone>\" \\\n  --prompt-file \"{baseDir}/references/scout-prompt.md\"\n```\n\n## Publisher\n\nTakes pending posts and publishes them to the channel.\n\n```bash\n# For each time from config.cronPublisherTimes:\nopenclaw cron add \\\n  --name \"content-pub-<N>\" \\\n  --schedule \"<config.cronPublisherTimes[N]>\" \\\n  --timezone \"<config.timezone>\" \\\n  --prompt-file \"{baseDir}/references/publisher-prompt.md\"\n```\n\n## Management\n\n```bash\n# List crons\nopenclaw cron list\n\n# Remove a cron\nopenclaw cron remove --name \"content-scout-1\"\n\n# Check next trigger\nopenclaw cron status\n```"},{"path":"references/publisher-prompt.md","content":"# Cron: Publisher\n\nRead {baseDir}/SKILL.md — it contains full content system documentation.\nRead the `tg-channel-manager` skill config from openclaw.json.\n\n## Task\n\nPublish one pending post from content-queue.md to the Telegram channel.\n\n## Steps\n\n1. Read content-queue.md\n2. Find posts with **pending** status\n3. If there are no pending posts — **DO NOTHING**. Do not generate content yourself.\n4. Check how many posts have already been published TODAY (via `message tool action=search`). If `config.maxPostsPerDay` or more — do not publish.\n5. Pick one post. **Alternate rubrics** when possible: check the last published post — if its rubric matches the current one, pick a post with a different rubric (if available in pending).\n6. Append the signature to the post text: `config.postStyle.signature`\n7. For news, add `config.postStyle.newsFooter` (if not empty)\n8. For articles, add `config.postStyle.articleFooter` (if not empty)\n9. Publish via:\n   ```\n   message tool (action=send, channel=telegram, target=<config.channelId>, text=\"post text\")\n   ```\n10. **Remove** the published entry from content-queue.md\n11. Add to the dedup index:\n    ```bash\n    python3 {baseDir}/scripts/dedup-check.py --base-dir . --add <msgId> --topic \"topic\" --links \"url\"\n    ```\n\n## Rules\n\n- Maximum 1 post per run\n- Maximum `config.maxPostsPerDay` posts per day\n- DO NOT generate content yourself — only publish pending posts\n- Language: `config.language`"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":"Universal config-driven content pipeline engine for any Telegram channel: news search via SearXNG, drafts, scheduled publishing, deduplication. All channel s... Skill: TG Channel Manager Owner: axisrow Summary: Universal config-driven content pipeline engine for any Telegram channel: news search via SearXNG, drafts, scheduled publishing, deduplication. All channel s... Tags: automation:0.0.1, channel:0.0.1, content:0.0.1, latest:0.0.3, searxng:0.0.1, telegram:0.0.1 Version history: v0.0.3 | 2026-02-23T13:00:09.332Z | user tg-channel-manager 0.0.3 - Major refactor: new comman","editorialQuality":{"score":100,"threshold":65,"status":"ready","wordCount":1197,"uniquenessScore":47,"reasons":[]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-11T21:13:22.414Z","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-11T21:13:22.414Z","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-12T18:07:59.420Z","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"}]}}}