Install
$ agentstack add skill-qwwiwi-agentos-skills-public-agentos-content ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
AgentOS Content Pipeline
Authoritative guide for writing and shipping lessons / bonuses on `. Read this before touching anything in apps/web/app/intensive/lesson/[id]/page.tsx or the intensive_bonuses` Supabase table.
When to use
- Adding a new bonus (текстовый гайд, без видео)
- Rewriting an existing lesson (e.g., changing structure, adding steps)
- Updating prompts / repos / outcome / skills inside an existing bonus
- Shipping any content change to production
Не использовать для
- Изменений auth / payments / API endpoints (это отдельный стек)
- Бекенд миграций (Supabase schema changes — отдельный workflow)
- Изменений рендерера блоков (
UnifiedBlockRenderer.tsx) без понимания всех уроков
Workflow at a glance
1. Author Python source-of-truth file → /tmp/lessonN_steps.py
2. Generate TS mock from source → python3 /tmp/update_mock_lN.py
3. Patch Supabase DB from same source → ssh thrall + python3 patch_db_lN.py
4. Build Next.js standalone → npm run build
5. Stage tarball + scp to prod server → /tmp/web-stage-vN/ → /tmp/web-deploy.tgz
6. Unpack on prod + PM2 restart → cd /var/www/ && tar -xzf
7. Verify HTTP 200 + visible content → curl https:///intensive/lesson/N
8. **Visual verify (MANDATORY)** → agent-browser → screenshot mobile → проверить глазами
9. Commit + push → / main
Critical rules (read before any change)
- Source-of-truth is Python, not TS or JSON. One Python file drives both mock and DB —
so they NEVER diverge. See references/02-source-of-truth.md.
re.subreplacement strings interpret\\nas newline. This will silently break
your generated TypeScript with «Unterminated string constant». Always wrap repl in lambda m: repl_str. See references/06-pitfalls.md Pitfall #1.
- Stale
/tmp/lessonN_steps.pyon Thrall.patch_db.pydoes
sys.path.insert(0, '/tmp'). If an old version sits in /tmp (from a previous session), it will load that one instead of yours and silently patch the WRONG content. Always cp /root/lessonN_steps.py /tmp/lessonN_steps.py before running patch_db. See Pitfall #2.
- Bonus pages don't show video or timecodes.
bonusN !== nullin
apps/web/app/intensive/lesson/[id]/page.tsx controls this. Don't accidentally re-enable them.
- No ID buttons on any block. Earlier ID copy was visual noise — removed from
step / code / prompt / mcpconfig / agentconfig. Only main «Копировать» (content) button remains.
- Production deploy goes to prod server (), NOT Thrall. DNS for
` points at prod server. There IS a shadow PM2 on Thrall :3020 — deploying there looks green on internal curl but prince sees old code. Always dig +short ` before deploy.
- Service-role-key NEVER in chat output.
bot/.envon Thrall contains
SUPABASESERVICEROLE_KEY which bypasses RLS. Never cat bot/.env, never tr "\0" "\n" .
- READ README перед build/deploy (HARD RULE, 2026-05-13). Перед
npm run build
либо правкой env / deploy скриптов / infra — обязательно Read README.md репо целиком (или Grep по «deploy», «env», «host», «prod», «production»). Не доверяй .env.example (часто staging-значения) и устаревшим skill-файлам. README на HEAD — canonical. Эту ошибку уже один раз получили (NEXTPUBLICAPIBASEURL из staging значения сломал prod). См. Pitfall #11 + core/rules.md главное правило.
- «Материалы» эфира = поле
materials, неblocks(HARD RULE). На странице эфира
вкладка-счётчик «Материалы · N» считает из intensive_eth_details.materials (массив {name, desc, url, filename}), НЕ из link-блоков внутри blocks. После добавления link-блоков в описание шага обязательно параллельно PATCH materials тем же набором. См. Pitfall #15.
- Cabinet счётчики материалов — хардкод-мок (HARD RULE).
apps/web/app/intensive/cabinet/page.tsx
имеет массив BROADCASTS с полями materials/lessons/open зашитыми статикой. Ничего не читает из БД. При добавлении материалов к эфиру N — параллельно править BROADCASTS[N-1].materials и делать полный rebuild + redeploy. См. Pitfall #16.
- Hot-patch скомпилированных chunks с тем же hash — антипаттерн (HARD RULE).
Браузер кеширует chunk по hash в имени файла как immutable. Правка содержимого без смены hash → у существующих посетителей старый код, у новых — новый. Всегда полный npm run build (получит новый hash) → tarball → scp → pm2 restart. См. Pitfall #12.
- Статика только вне
/intensive/*префикса. Next.js app router имеет роуты
/intensive/cabinet, /intensive/eth/[id], /intensive/lesson/[id] и т.д. Файлы в public/intensive//... → HTTP 404 из-за конфликта. Паттерн в проекте: public/efir-N/... → /efir-N/.... После добавления статики в public/ — обязательный pm2 restart (Next.js standalone кеширует listing при старте, см. Pitfall #14).
- Контент урока живёт в 4 местах, не в одном (HARD RULE). После любого
изменения контента урока обязательно обновить ВСЕ 4 источника, иначе listing-страницы покажут старое:
- DB
intensive_lessons.blocks— детальная страница BONUS_LESSONS/ONBOARDING_LESSONSmock вapp/intensive/lesson/[id]/page.tsx— SSR fallbackLESSONS[]hardcoded вapp/intensive/cabinet/onboarding/page.tsx— список предобученияFEED_ITEMS[]hardcoded вapp/intensive/materials/page.tsx— агрегация материалов
Обязательный grep-чеклист после изменения: ``bash grep -rn "ONBOARDING_LESSONS\|BONUS_LESSONS\|FEED_ITEMS\|LESSONS\[" apps/web/app/ `` Visual verify (#8) ловит автоматически — если делать скриншот listing-страниц, а не только детальной. См. Pitfall #10.
Detailed references
Open ONLY the reference you need (don't load all on every task):
references/01-architecture.md— bonus vs lesson, ID mapping (lesson 10 ↔ bonus 1),
full block-types table, where each piece of content lives.
references/02-source-of-truth.md— Python source file structure, helper conventions,
step / prompt / timecode / repo formats. Includes templates/lesson_steps.py.tmpl.
references/03-mock-and-db.md— howupdate_mock.pyrewritespage.tsx, how
patch_db.py PATCHes Supabase, where service-role-key lives, env path on Thrall.
references/04-deploy.md— exact tarball layout, scp steps, PM2 commands, verify
curl, rollback via .next.bak.* directories.
references/05-frontend-rules.md— hide rules (video / timecodes / ID buttons),
block-types white-list, mockToBlocks adapter, render order (timecodes → description → rest).
references/06-pitfalls.md— 17 silent failure modes that will waste your hour.
Особо критичны для эфир-страниц: #11 .env.example ломает prod API URL, #12 hot-patch chunk не инвалидирует кеш, #13 public/intensive/* 404 из-за app router конфликта, #14 Next.js standalone кеширует public/ listing (нужен PM2 restart), #15 «Материалы» эфира — отдельное поле БД materials, не blocks, #16 cabinet counters — хардкод-мок, #17 material card был `` без href (баг репо, починен 2026-05-13).
references/07-video-pipeline.md— видео-уроки end-to-end: Kinescope upload через TUS
(X-Video-Title quirk), CSP frame-src для iframe, тайм-коды через AssemblyAI universal-2 + Sonnet по word-level транскрипту, транскрипты как public/transcripts/lesson-N.md.
Video lessons pipeline (NEW, 2026-05-08)
Для уроков с видео-эфиром нужны три связанные сущности — все три в скилле автоматизированы.
1. Kinescope embed на странице урока
- Frontend:
app/intensive/lesson/[id]/page.tsxрендерит iframehttps://kinescope.io/embed/{kinescope_video_id}?playsinline=1через padding-top 56.25% хак (НЕ через Tailwindaspect-video+absolute— на iOS Safari лазерчатый. См. Pitfall #11 в 07). - Source of truth для video_id:
intensive_lessons.kinescope_video_id(DB) ИЛИLessonMock.kinescopeId(mock fallback). Backend/api/platform/intensive/lessonsотдаётkinescope_video_idв DTO — фронт preferит DTO, mock — fallback. - CSP (HARD RULE):
next.config.tsДОЛЖЕН содержатьframe-src 'self' https://kinescope.io https://*.kinescope.io+media-srcдля CDN; Caddy/etc/caddy/CaddyfileДОЛЖЕН отдавать тот же CSP (он перезаписывает Next-заголовок). Без этого iframe чёрный без сообщения. См. 07-video-pipeline.md секция «CSP и Caddy». - Upload через API:
POST https://uploader.kinescope.io/v2/videoсо всем файлом в body +X-Video-Title(b64 от ASCII-плейсхолдера, потому что header'ы ASCII-only) +X-Parent-Id. После — PATCH/v1/videos/{id}с настоящим title (cyrillic). См. 07 секция «Upload».
2. Тайм-коды по реальным переходам темы
Двухэтапный пайплайн вместо ручной разметки или равномерных интервалов:
- Транскрибация в AssemblyAI:
language_code=ru,speech_models=["universal-2"](устаревшийspeech_modelстрокой больше не работает — fallback ругается). Получаем words сstart/endв ms. - Сегментация в окна по 30s, отправка в Sonnet через Agent tool с просьбой найти 5-7 точек где явно меняется тема. Sonnet возвращает
{ts: int_seconds, label: "..."}. НЕ генерируй тайм-коды через OpenRouter — только черезAgent(subagent_type=general-purpose, model=sonnet)per rules.md. - Запись в DB как блоки
type=timecodeс форматом{id, ts: "MM:SS", type, label}, вставленные после meta/outcome/skills и перед steps. Параллельно те же тайм-коды в mockLessonMock.timecodes[]для SSR.
3. Транскрипт-файлы для скачивания
- Файлы лежат в
apps/web/public/transcripts/lesson-{N}.md— markdown с заголовками## MM:SS — labelпо тайм-кодам и абзацами по паузам (gap > 800ms). - Кнопка «Скачать транскрипт» на странице урока показывается между видео и тайм-кодами для
lessonN ∈ [1..5](расширять список по мере появления новых транскриптов). Атрибутdownload="agentos-lesson-{N}-transcript.md". - Транскрипт = бонус для AI-репетитор-флоу из L1: ученик скачивает .md, вставляет в Claude/GPT, расспрашивает.
См. полный пайплайн в references/07-video-pipeline.md.
Templates
In templates/:
lesson_steps.py.tmpl— copy to/tmp/lessonN_steps.py, fill in TITLE / DURATION /
DESCRIPTION / OUTCOME / SKILLS / PROMPTS / REPOS / TIMECODES / STEPS.
update_mock.py.tmpl— copy to/tmp/update_mock_lN.py, change bonus_number,
block boundary identifiers ('11': { / '12': {).
patch_db.py.tmpl— copy to/tmp/patch_db_lN.py, changebonus_number=eq.N.
Quickstart: add a new bonus in 5 minutes
# 1. Copy templates, fill in content
cp .claude/skills/agentos-content/templates/lesson_steps.py.tmpl /tmp/lesson12_steps.py
cp .claude/skills/agentos-content/templates/update_mock.py.tmpl /tmp/update_mock_l12.py
cp .claude/skills/agentos-content/templates/patch_db.py.tmpl /tmp/patch_db_l12.py
# Edit lesson12_steps.py — add TITLE, DESCRIPTION, STEPS, etc.
# Edit update_mock_l12.py — change "'11'" → "'12'", "'12'" → "'13'" (block boundary)
# Edit patch_db_l12.py — change "bonus_number=eq.2" → "bonus_number=eq.3"
# 2. Update mock + DB
python3 /tmp/update_mock_l12.py
scp /tmp/lesson12_steps.py /tmp/patch_db_l12.py root@:/root/
ssh root@ 'cp /root/lesson12_steps.py /tmp/lesson12_steps.py && \
set -a && source /home//intensive-agentos/bot/.env && set +a && \
cd /root && python3 patch_db_l12.py'
# 3. Build + deploy (see references/04-deploy.md for full steps)
cd apps/web && npm run build
# ... stage tarball, scp, unpack on prod server, PM2 restart, verify
# 4. Commit + push
git add apps/web/app/intensive/lesson/\[id\]/page.tsx
git commit -m "feat(lesson 12): новый бонус про X"
git push origin main
Where content lives
| Layer | Location | |---|---| | Python source-of-truth (current session) | /tmp/lessonN_steps.py | | Templates (this skill) | .claude/skills/agentos-content/templates/ | | TS mock (SSR fallback) | apps/web/app/intensive/lesson/[id]/page.tsx (BONUS_LESSONS / ONBOARDING_LESSONS) | | Block renderer | apps/web/components/blocks/UnifiedBlockRenderer.tsx | | Block types schema | apps/web/lib/unified-block-types.ts | | DB (live source for client fetch) | Supabase intensive_bonuses table, column blocks (JSON) | | Backend (FastAPI gunicorn :8095) | /home//intensive-agentos/api/ on Thrall | | Production frontend | prod server → /var/www// (PM2 :3020) | | Staging frontend | Thrall → /home//intensive-/ (PM2 :3010) | | Repo | / (private) |
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: qwwiwi
- Source: qwwiwi/agentos-skills-public
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.