All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
The 2026-04-27 cybersecurity audit (via /cybersecurity skill) identified
1 CRITICAL + 5 HIGH + 14 MEDIUM + 11 LOW + 8 INFO findings (39 total).
This release closes all of them across 10 focused commits.
- CRITICAL VULN-001:
setup_image_mcp.pydefaulted to project-local.mcp.json(which was tracked) and wrote literalGOOGLE_AI_API_KEY. Default flipped to--global(writes user-private~/.claude/settings.json, mode 0600);--projectopts in to env-expansion-only mode and refuses to write into a tracked file. - HIGH:
.mcp.jsonremoved from git tracking, added to.gitignore; new tracked.mcp.example.jsontemplate with env-expansion + pinned@ycse/nanobanana-mcp@1.1.1. - HIGH:
_save_oauth_tokenand NotebookLM_save_browser_statenow use atomic write +chmod 0o600._harden_permshelper applied to every credential-write site. - HIGH: OAuth flow gains CSRF state token via
secrets.token_urlsafe, validated in handler with 403 on mismatch. Listener bound to 127.0.0.1. - HIGH: 4 hash-pinned lock files (1915 LoC) for all pip manifests via
pip-compile --generate-hashes --strip-extras --allow-unsafe. - HIGH: README install ordering reframed (clone+checkout-tag now recommended; curl-pipe-bash documented as convenience with trust caveat).
- OAuth scopes downgraded to per-command least-privilege (
gsc_readonly + ga4default;--scopesflag for explicit elevation). --no-sandboxremoved from NotebookLM Chromium launch (env opt-in only).sync_flow.pylockfile drift now BLOCKS viasys.exit(2)unless--allow-driftexplicitly passed; drift fires before filesystem mutation.google_report.py--domainwhitelist regex + path containment check.- CI workflow gains top-level
permissions: contents: read, concurrency cancel-in-progress, andpip install -e ".[dev]"(was unpinned). - Dependabot adds 3 nested-manifest entries (was missing 80% of dep surface).
pyproject.tomladvanced extras now bounded; new[ads]group declares previously-phantomgoogle-adsdep.- GitHub Actions SHA-pinned (
actions/checkout+actions/setup-python).
traceback.print_exc()in NotebookLM error path replaced with clean error; verbose trace gated behindBLOG_DEBUGenv.- 6 bare
except:blocks changed toexcept Exception:so signals propagate. __init__.pyimport-time side effects removed (no more silent venv.create + Chrome download on test discovery).- API key masking changed from
key[:8]+...+key[-4:]to length-only. - Unexecutable Bash instruction removed from
blog-writeragent prompt. uninstall.shanduninstall.ps1now globblog-*(was static list missing v1.7.0 sub-skills) and purge~/.config/claude-seo/credentials.- CLI input length caps on
ask_question.pyandnotebook_manager.py.
install.ps1+uninstall.ps13-argJoin-Pathcalls (PS 6.0+ only) rewritten as nested 2-arg form. Default Windows 10/11 ships PS 5.1; the prior code would fail with "A positional parameter cannot be found" on every install attempt.- The
??null-coalescing operator (also PS 6.0+) was already removed in an earlier hotfix commit (96ef396).
test_google_auth_write_secret_atomic_sets_mode_0600: behavioral test loading the helper viaimportlib.spec_from_file_location+tmp_path.test_notebooklm_credential_files_contain_chmod_hardening: static test requiring_harden_perms(count >= 2 (def + at least 1 call).test_mcp_json_is_gitignored: regression gate for.gitignoreentry.test_user_invokable_skills_have_complete_frontmatter(NEW): asserts every user-invokable SKILL.md hasdescription,argument-hint, andlicensefields. Closes the verifier blind spot that allowed blog-rewrite (and 14 other skills) to ship without these fields.
- New comprehensive
SECURITY.md: vulnerability disclosure flow, in/out of scope, T1-T11 trust boundaries with STRIDE, dual-use technology notes (patchright stealth-fork rationale, WebFetch indirect prompt injection risk model, sync_flow defenses), audit history, hardening checklist. docs/MCP-INTEGRATION.mdupdated with new--globaldefault flow.skills/blog-image/SKILL.mdsetup section reflects new defaults + pinning convention.docs/COMMANDS.mdupdated to cover all 27 user commands (was 17).agents/blog-researcher.mdadds explicit prompt-injection framing for WebFetch / WebSearch content (T9 boundary defense).agents/blog-writer.mdclarifies dual install path for analyze script.
- Generated 4 hash-pinned lock files (
requirements.lockat root + 3 nestedskills/*/scripts/requirements.lock). All install paths viasetup_environment.pynow prefer--require-hashes -r .lockwhen present. - pyproject.toml: bound previously-unbounded
advancedextras (lxml,jsonschema,spacy,sentence-transformers,scikit-learn,language-tool-python); syncedcoreupper bounds withrequirements.txt; added[ads]optional group withgoogle-ads.
- All 27 user-invokable SKILL.md files now declare
argument-hintandlicense: MITconsistently. Caught by full-skill test pass + 9-agent meta-audit; previously 15 skills were missing one or both fields.
- 7-agent cybersecurity audit dispatch (parallel, single message)
- 28-agent full-skill test dispatch (one per sub-skill, parallel)
- 9-agent meta-audit (re-audit the audit + fix arc)
- Independent code-reviewer agent caught 5 issues post-commit (build-system missing, bare-filename crash, PS 5.1 incompatibility, weak test, missing ValueError handler) -> hotfix commit applied.
- Codex GPT-5.5 high-reasoning council used 4 times for plan validation; each returned APPROVE-WITH-CHANGES with substantive corrections that materially improved the plan.
blog-write/SKILL.mdPhase 5 extraction: currently 535 lines, ideal is < 500. Extract Phase 5 to a reference file in next iteration.sentence-transformersupper bound<5.0.0is one major behind current 5.4.1; re-evaluate when next minor lands.- E-E-A-T overlap consolidation across
eeat-signals.md,geo-optimization.md,quality-scoring.md(architectural).
blog-clustersub-skill (winner of the AI Marketing Hub Pro Hub Challenge, March 2026, by Lutfiya Miller). Semantic topic-cluster planning + execution engine. SERP-based keyword grouping, hub-and-spoke architecture, sequentialblog-writeorchestration with shared cluster context and automatic internal-link injection. XSS-hardened cluster-map.html (no inline JavaScript). Adapted from semantic-cluster-engine.blog-multilingualsub-skill (by Chris Mueller, AI Marketing Hub Pro). One-command international publishing. Orchestratesblog-write,blog-translate,blog-localize, plus optionalseo-hreflangintegration. Adapted from claude-blog-multilingual.blog-translatesub-skill (by Chris Mueller). SEO-optimized translation with format preservation, machine-translation artifact detection, and locale-correct number/date/currency formatting.blog-localizesub-skill (by Chris Mueller). Cultural deep-adaptation with built-in profiles for DACH, Francophone, Hispanic, and Japanese markets, plus a custom-locale template.blog-locale-auditsub-skill (by Chris Mueller). Multilingual quality control: completeness matrix, hreflang correctness, meta-tag parity, freshness checks.blog-translatorspecialized agent (noBashtool, per the v1.9.6 lesson from claude-seo).blog-flowsub-skill. FLOW framework integration (github.com/AgriciDaniel/flow, CC BY 4.0 prompt content + MIT code). Commands:/blog flow [find|optimize|win|prompts|sync]. Surfaces 30 blog-applicable evidence-led prompts; the local-SEO stage is intentionally excluded (use claude-seo for those).scripts/sync_flow.py. Pulls FLOW references from GitHub. Stdlib only. HTTPS-only host allowlist (api.github.com). 5 MB cap. Atomic writes. Path-traversal guard. Anonymous-first GitHub API. Supports--dry-runand--ref <sha>pinning. SHA-256 lockfile drift detection. Injects CC BY 4.0 license header on every synced markdown file plus the auto-generated index README.tests/test_security_guardrails.py. Four mechanical pytest gates that fail CI if (1) any agent grantsBash, (2) any SKILL.md uses the invalidallowed-toolsfield, (3) skill names collide, or (4) the FLOW sync script loses a security invariant.CONTRIBUTORS.mdcrediting Pro Hub Challenge contributors and recording the integration decisions.
- Plugin description bumped to mention 27 commands, 5 agents, FLOW + cluster + multilingual capabilities.
- Marketplace description updated to "28 skills, 5 agents, FLOW framework integration, semantic topic-cluster execution, multilingual publishing".
skills/blog/SKILL.mdorchestrator: routing entries added forcluster,multilingual,translate,localize,locale-audit, andflow. Quick Reference table updated. Version bumped to 1.7.0.CLAUDE.mdfile counts updated (28 sub-skills, 5 agents).- Plugin keywords expanded to include
flow-framework,topic-clusters,hub-and-spoke,multilingual,translation,localization,hreflang,i18n.
- Pre-existing security debt: removed
Bashfromagents/blog-reviewer.mdtools list. The agent scores text and only needsRead,Grep,Glob. Aligns with the v1.9.6 lesson from claude-seo (prompt-injection blast radius on agents with shell access). Now enforced mechanically bytest_no_bash_tool_in_any_agent_frontmatter.
- install.ps1: Fixed Windows PowerShell 5.1 ParameterBindingException (
irm|iextoiex (irm)) - install.ps1: Corrected Python version warning from 3.12+ to 3.11+
- ci.yml: Bumped actions/checkout and actions/setup-python from v4/v5 to v6
- docs/INSTALLATION.md: Updated Windows one-liner to match install.ps1 fix
- 29 corrections across API endpoints, crawler specs, schema markup, and distribution playbook
- GA4 quota corrected from 25K to 200K Core Tokens/day
- Removed misquoted "46% reading mode" stat; replaced with actual Kevin Indig finding
- Added 8 new AI crawlers to ai-crawler-guide.md
- BlogPosting schema properties corrected from "Required" to "Recommended" per Google docs
- Sweep-up: 5 residual attribution fixes from Areas 3-7 audit
- Corrected 20 misattributed or unverifiable statistics in google-landscape-2026.md and geo-optimization.md
- Removed fabricated Mueller quote; replaced with paraphrase of documented position
- Removed unverifiable +340% Seenos citation claim from SKILL.md, content-rules.md, schema-stack.md, distribution-playbook.md
- Added caveats to FAQPage (+28%, sponsored SEL article), G2 stats (self-reported), B2B SaaS decline (single case study)
- Updated ChatGPT users 800M to 900M, AI Mode countries 120 to 200+, Hidden Gems 77% to 70.85%
- blog-google sub-skill: Google API integration with 13 commands across 4 credential tiers. Includes PageSpeed Insights, CrUX Core Web Vitals (25-week history), Search Console performance, URL Inspection, Indexing API, GA4 organic traffic, NLP entity analysis, YouTube video search, Google Ads Keyword Planner, and PDF/HTML report generation. Contains 11 Python scripts in isolated venv. Shares config with claude-seo at
~/.config/claude-seo/google-api.json. - YouTube video embedding: Blog posts now discover and embed 2-3 relevant YouTube videos using srcdoc lazy-loading pattern (~5KB vs ~500KB per embed). Integrated into blog-write (Phase 2 research + Phase 5 embedding), blog-rewrite (audit + inject), and blog-schema (VideoObject generation). Supports MDX, HTML, Markdown, and Hugo embed formats with noscript fallback for AI crawlers.
- VideoObject JSON-LD schema: blog-schema now generates VideoObject for embedded videos (up to 7 schema types per page, from 6). Added to schema-stack.md reference with @id pattern
#video-{N}. - video-embeds.md reference: New reference file with quality criteria (0-100 scoring), embed placement strategy, platform-specific code patterns, and graceful degradation.
- Google API integrations in existing workflows: blog-seo-check (optional PSI/CrUX), blog-rewrite (NLP entity analysis), blog-geo (GSC performance), blog-researcher (YouTube video discovery).
- Plugin compliance: Removed non-standard
allowed-toolsfrontmatter field from all 22 SKILL.md files per Claude Code plugin specification. Only valid fields remain: name, description, user-invokable, argument-hint, compatibility, license, metadata. - CLAUDE.md development rules: Clarified SKILL.md frontmatter field requirements and reference file size guidelines.
- plugin.json: Removed invalid
skillsarray of objects that failedclaude plugin validate(skills auto-discovered fromskills/directory) - Agent frontmatter: Removed unsupported
context: forkfield from all 4 agents (blog-researcher, blog-writer, blog-seo, blog-reviewer) per plugin agent spec - Version alignment: Synced pyproject.toml version with plugin.json (was 1.5.0, now 1.6.2)
- Marketplace support: Created
.claude-plugin/marketplace.jsonfor self-hosted marketplace distribution (/plugin marketplace add AgriciDaniel/claude-blog) - plugin.json
repositoryfield: Source code URL for marketplace discoverability - plugin.json
keywordsfield: 14 tags for marketplace search (blog, seo, content, writing, ai-citations, geo, aeo, eeat, etc.)
- blog-notebooklm sub-skill: Query NotebookLM for source-grounded research with 10 Python scripts and 2 reference docs
- blog-audio sub-skill: Generate audio narration via Gemini TTS with 30 voice options, summary/full/dialogue modes, and 5 Python scripts
- Dynamic skill discovery in installers (fixes #8, fixes missing blog-notebooklm/blog-audio)
- Replaced remaining em dashes in .gitattributes and requirements.txt
- Updated "Claude Banana" reference to "Banana Claude" after upstream repo rename
- blog-persona sub-skill: Writing persona management with NNGroup 4-dimension tone framework, configurable readability bands (Consumer/Professional/Technical), and style enforcement
- blog-cannibalization sub-skill: Keyword overlap detection across blog posts with local-only (grep) and DataForSEO API modes, severity scoring, and merge/differentiate recommendations
- blog-factcheck sub-skill: Statistics verification pipeline that fetches cited source URLs and scores claim confidence (exact match, paraphrase, not found)
- blog-taxonomy sub-skill: CMS taxonomy management supporting WordPress REST, Shopify GraphQL, Ghost, Strapi, and Sanity. Tag suggestion, sync, and audit workflows
- CTA placement reference: Content-type-specific CTA positioning rules with HubSpot statistics (202% better contextual CTAs, 266% more conversions with single CTA)
- Visual rhythm enforcement: Mandatory visual element (image/chart/callout) every 300-500 words in blog-write and blog-writer agent
- Link deduplication check: Step 5.5 in blog-seo-check flags duplicate URLs in body content
- Creative Director prompting: 4-dimension professional image prompting (Lighting, Camera, Film Stock, Material) in blog-image prompt engineering reference
- TL;DR replaced with Key Takeaways: Default summary box label changed to "Key Takeaways" with 3-5 bullet format. Configurable per persona. Backward compatible (accepts TL;DR, Key Takeaways, The Bottom Line, What You'll Learn, At a Glance, In Brief)
- Readability bands by audience: Consumer (Grade 6-8), Professional (Grade 8-10), Technical (Grade 10-12) with default at Grade 7-8
- analyze_blog.py: Updated summary box detection to recognize all 6 label variants
- blog-image models: Added Imagen 4 pricing, legacy model deprecation note (June 1, 2026), blog image post-processing pipeline spec
- Updated install scripts to handle 4 new sub-skills and personas directory
- Updated orchestrator routing table, Quick Reference, and Sub-Skills table (19 sub-skills, 17 commands)
- blog-image sub-skill: AI image generation and editing for blog content via Gemini MCP (
@ycse/nanobanana-mcp)- 6-component Reasoning Brief system (Subject, Action, Context, Composition, Lighting, Style)
- 6 blog-optimized domain modes (Editorial, Product, Landscape, UI/Web, Infographic, Abstract)
- Commands:
/blog image generate,/blog image edit,/blog image setup - 3 reference files: gemini-models.md, mcp-tools.md, prompt-engineering-blog.md
- 2 setup scripts: setup_image_mcp.py, validate_image_setup.py
- MCP integration: nanobanana-mcp server config in
.mcp.jsonfor Gemini image generation - blog-write: AI image generation as alternative/supplement to stock photos in Phase 2 Research
- blog-rewrite: AI image generation for missing/insufficient images in Phase 2 and Phase 4g
- blog-researcher: AI image recommendation output when stock photos are insufficient
- visual-media.md: Option 3 - AI-Generated Cover documentation with domain mode guidance
- Updated install scripts (install.sh, install.ps1) to handle blog-image references and scripts
- Updated orchestrator routing table, Quick Reference, and Sub-Skills table for blog-image
- Updated docs: COMMANDS.md, MCP-INTEGRATION.md, INSTALLATION.md with image generation docs
- Updated README.md: commands table, architecture diagram, feature descriptions, badge count (13→15)
- Sub-skill count: 14 → 15 (13 user-facing + 1 internal chart + 1 image generation)
- SKILL.md:
license,compatibility, andmetadatafields per Agent Skills spec (agentskills.io) - plugin.json:
version,homepage,licensefields;skillsarray declaring all 14 skills (marketplace readiness);blog-chartmarkeduser-invocable: false - GitHub issue template and PR template (community health files)
- README.md: Removed broken
/plugin install claude-blog@AgriciDaniel(not yet registered in marketplace); corrected Python badge3.12+→3.11+; added inline note clarifyingblog-chartis internal - docs/INSTALLATION.md: Removed "Plugin Install (Recommended)" section with broken command; corrected Python
3.12+→3.11+(aligns withpyproject.toml >=3.11and CI matrix) - docs/INSTALLATION.md: Added
blog-chartto manualmkdirbrace expansion (was missing from 13-skill list) - CLAUDE.md: Corrected Python version reference
3.12+→3.11+
- install.ps1: Removed dead
$dirsvariable block (declared but never used); updated paths forskills/blog/restructure; addedblogskip in sub-skill loop to prevent double-copy - skills/blog/SKILL.md: Corrected
compatibilityfield Python version3.12+→3.11+; correcteduser-invocable→user-invokable(correct Agent Skills spec spelling) - skills/blog-chart/SKILL.md: Added
user-invokable: falseto match plugin.json declaration; corrected attribute spelling
- Deleted
firebase-debug.log(gitignored debug artifact); deleted stale remote branchclaude/review-plugin-testing-practices-eVVOU
- Plugin ecosystem support:
.claude-plugin/plugin.jsonfor/plugin installcompatibility - 44 pytest unit tests for
analyze_blog.py, covers frontmatter, headings, paragraphs, images, AI detection, citations, FAQ, freshness, readability, links, schema, and integration tests - GitHub Actions CI: 3 jobs - Python tests (3.11 + 3.12), SKILL.md frontmatter validation, plugin.json validation
- DataForSEO MCP integration documentation, recommended primary MCP server for live SEO data (SERP, keywords, backlinks, on-page, domain analytics, content analysis, AI optimization)
pyproject.tomlwith dependency groups (core, advanced, dev)CONTRIBUTING.mdwith development guidelines.mcp.jsonfor optional MCP server configuration- Skill evaluation scenarios (7 trigger test cases)
- Directory restructure:
blog/→skills/blog/(official Anthropic plugin layout) - Updated all internal path references across skills, docs, and install scripts
- README updated with plugin install as primary method
- MCP-INTEGRATION.md updated with DataForSEO as recommended integration
- install.sh: Restored
TEMP_DIRglobal scope fix (lost during restructure) - install.sh: Removed
--break-system-packagespip flag (security concern) - install.sh: Removed redundant
mkdirand double-copy ofskills/blog/ - CI: Fixed lint-markdown grep matching legitimate
skills/blog/references/paths - Docs: Fixed 11 instances of double
skills/skills/paths in INSTALLATION.md and TROUBLESHOOTING.md
--break-system-packagespip install flag
- install.sh: Move
TEMP_DIRdeclaration to global scope so theEXITtrap can access it aftermain()returns (fixes "unbound variable" error withset -uwhen installing viacurl | bash)
- Readability layer upgrade with research-backed thresholds (120+ sources):
- Flesch target: 45-60 → 60-70 (aligns with Yoast, GEO, WCAG, Raptive data)
- Paragraph hard limit: 100 → 150 words (200 = Yoast red)
- Ideal paragraph range: 40-55 → 40-80 words
- H2 heading frequency: 150-200 → 200-300 words
- Content Quality redistribution: Depth 8→7, Readability 6→7
- New automated checks in
analyze_blog.py: passive voice estimation, transition word percentage, AI trigger word detection (26 words), sentence length distribution - New reference sections in
google-landscape-2026.mdandgeo-optimization.mdfor readability signals - 16 files updated across references, script, skills, agents, and docs
- YouTube demo video link in README
- Header image and demo GIFs (
assets/)
- Placeholder
screenshots/directory
- Built-in SVG chart generation (
blog-chartsub-skill), eliminates external/svgdependency- Supports 7 chart types: horizontal bar, grouped bar, donut, line, lollipop, area, radar
- Dark-mode compatible, accessible (WCAG), platform-aware (HTML/JSX auto-detection)
- Image URL verification in researcher agent, validates HTTP 200 before embedding
- Mid-writing readability check in writer agent, self-checks Flesch targets before returning
- Image density guidelines by content type in visual-media.md
- claude-blog is now fully self-contained, no external skill dependencies required
- Integration section updated to list companion skills as optional
- Installer scripts updated for 13 sub-skills
- External
/svg//svg-chartskill dependency
- 12 slash commands: write, rewrite, analyze, brief, calendar, strategy, outline, seo-check, schema, repurpose, geo, audit
- 12 reference documents loaded on-demand (RAG pattern):
- google-landscape-2026, geo-optimization, content-rules, visual-media, quality-scoring
- eeat-signals, content-templates, ai-crawler-guide, schema-stack, platform-guides, distribution-playbook, internal-linking
- 12 content type templates: how-to, listicle, case study, comparison, pillar page, product review, thought leadership, roundup, tutorial, news analysis, data research, FAQ/knowledge base
- 4 specialized subagents: blog-researcher, blog-writer, blog-seo, blog-reviewer
- Python quality analysis script (
analyze_blog.py):- 5-category, 100-point scoring system (Content 30, SEO 25, E-E-A-T 15, Technical 15, AI Citation 15)
- Readability analysis via textstat (Flesch, Gunning Fog, SMOG, Coleman-Liau)
- AI content detection signals (burstiness, known AI phrases, vocabulary diversity)
- Schema detection via BeautifulSoup
- Batch mode with directory scanning
- Multiple output formats (JSON, markdown, table)
- Graceful degradation without optional dependencies
- Unix + Windows installers (install.sh, install.ps1) with one-command curl install
- Uninstaller (uninstall.sh) for clean removal
- Full documentation suite (docs/): Installation, Commands, Architecture, Templates, Troubleshooting, MCP Integration
- Main orchestrator:
skills/blog/SKILL.md(routes all 12 commands) - 12 sub-skills in
skills/blog-*/SKILL.md - 4 subagents in
agents/blog-*.md - 12 reference docs in
skills/blog/references/(loaded on-demand) - 12 content templates in
skills/blog/templates/
- Corrected phantom "January 2026 Authenticity Update" references to verified December 2025 Core Update (Dec 11-29, 2025)