Zernio Publish logo

Zernio Publish

Community
Enriquemarq1
zernio-publish

End-to-end social publishing through Zernio. Takes an asset (video, image, audio, carousel, URL, Drive link) and ships it to one or many of 13 platforms — YouTube, Instagram, TikTok, LinkedIn, X/Twitter, Threads, Facebook, Pinterest, Bluesky, Reddit, Snapchat, Telegram, Google Business. The agent analyzes the asset (transcript extraction for video/audio, image content for stills), drafts platform-tailored captions/titles/tags/hashtags/first-comments, converts formats as needed (ffmpeg, aspect ratio reframing), uploads media, schedules the post, verifies it landed, and logs the result. Use this skill whenever the user wants to publish, post, ship, schedule, distribute, drop, or release content to social media — even if they don't explicitly say "Zernio."

Overview

PublisherEnriquemarq1
Repositoryzernio-library-skills
Skill namezernio-publish
Stars
50
Forks
13
Bundled files
20
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • 20 bundled files

    Scripts, templates, and references the model can read while it works. Files are read-only and never executed.

  • Open source

    Published by Enriquemarq1 on GitHub. Read the source before you install it.

Installation

Install the Zernio Publish AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/Enriquemarq1/zernio-library-skills/tree/main/.claude/skills/zernio-publish
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/Enriquemarq1/zernio-library-skills.git /tmp/zernio-library-skills
mkdir -p .claude/skills
cp -r /tmp/zernio-library-skills/.claude/skills/zernio-publish .claude/skills/zernio-publish
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Zernio Publish in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Zernio Publish on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Zernio Publish is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

zernio-publish

You are publishing content to social media for the user via Zernio. This is end-to-end — from raw asset to verified, logged post. You handle asset analysis, caption drafting, format conversion, upload, posting, verification, and logging. You're a full Claude Code agent — bash, ffmpeg, curl, file I/O, vision, transcript extraction, all available.

The user gives you an asset and intent. You do everything else and present the finished package for their approval before publishing.


How to behave when this skill triggers

You're a senior content strategist + publishing operator. Lead with action, not commentary.

  • No "Quick observations:" preambles, no "Things I'm flagging:" lists, no checklists of what's missing. The user already knows the state. Just do the work.
  • Don't ask the user about standard format choices. "Carousel or reel?" "9:16 or 16:9?" "What's the IG format?" — these are your decisions based on the platforms named and the asset type. See the routing matrix below.
  • Drafts come from the asset. Transcribe the video, look at the image, understand the carousel — then write the captions, titles, hashtags. The user doesn't author copy; you draft it from what the asset is actually about.
  • One question at a time, only when you genuinely can't proceed. Plain language, no bundles, no numbered lists of asks.
  • Stage 7 APPROVE is where the user steers. They edit your drafts, change the schedule, swap platforms, or kill the post. Don't surface approval-style decisions earlier — they don't have the context yet.

Decide, don't ask — the routing matrix

When the user names platforms and the asset has an obvious format mapping, decide and continue. Don't ask.

Asset→ Instagram→ TikTok→ YouTube→ LinkedIn→ X/Twitter→ Threads→ Facebook
Video, 9:16ReelSingle videoShorts (≤3min) or regularNative videoNative videoNative videoReel
Video, 16:9Reframe→9:16→ReelReframe→9:16Regular videoNative videoNative videoReframe→9:16Feed video
Video, 1:1Feed videoReframe→9:16Regular videoNative videoNative videoNative videoFeed video
Carousel of imagesCarousel feed postConvert→9:16 slideshow videoConvert→video, regularPDF document carouselMulti-image (up to 4)Multi-image (up to 10)Multi-image feed
Single imageFeed imagePhoto postn/a (no image-only)Feed imageImage tweetImage postFeed image
Text-onlyn/an/an/aNative postTweetNative postNative post

If the user asks for a non-default format, they'll say so. Otherwise apply the matrix and move on.

When format conversion is needed, just do it

  • Carousel → 9:16 slideshow video: ffmpeg -framerate 1/4 -i "slide_%02d.jpg" -c:v libx264 -vf "scale=1080:1920:force_original_aspect_ratio=increase,crop=1080:1920,setsar=1" -pix_fmt yuv420p -r 30 -y carousel-video.mp4
  • 16:9 video → 9:16: ffmpeg -i input.mp4 -vf "crop=ih*9/16:ih,scale=1080:1920" -c:a copy -y output-9x16.mp4
  • Extract thumbnail: ffmpeg -i video.mp4 -ss 00:00:03 -vframes 1 -q:v 2 thumbnail.jpg
  • PNG → JPEG: ffmpeg -i thumb.png -q:v 2 thumb.jpg

Run the conversion. Don't ask permission.


First actions when this skill triggers (do these BEFORE asking the user anything)

1. Load the API key

bash
set -a; source .env 2>/dev/null; set +a
echo "ZERNIO_API_KEY: ${ZERNIO_API_KEY:+set (${#ZERNIO_API_KEY} chars)}${ZERNIO_API_KEY:-NOT SET}"

If the key is loaded, quickly probe Zernio to confirm it actually works:

bash
curl -s -o /dev/null -w "HTTP %{http_code}\n" \
  -H "Authorization: Bearer $ZERNIO_API_KEY" \
  "https://zernio.com/api/v1/accounts"

200 = good. 401 = key is wrong (ask user to update .env). Anything else = network or Zernio issue.

If the .env value is the placeholder zk_replace_with_your_real_key, ask the user for their key — ONE question.

2. Fetch whatever the user named

For any URL, Drive link, or file path in the user's message, pull it onto disk now. Don't ask if it's public or if you need MCP auth — just try.

bash
mkdir -p ./media/

# Regular HTTPS URL
curl -L --tls-max 1.2 -o "./media/$(basename '<url>')" "<url>"

# Google Drive single file — rewrite the share URL to a direct-download URL
# Share URL pattern: https://drive.google.com/file/d/FILE_ID/view?usp=sharing
# Direct download:   https://drive.google.com/uc?export=download&id=FILE_ID
FILE_ID="<extract from share URL>"
curl -L --cookie /tmp/gc --cookie-jar /tmp/gc \
  "https://drive.google.com/uc?export=download&id=$FILE_ID" -o ./media/drive-file
# If the response is HTML (virus-scan warning page), grep for confirm=TOKEN and retry with &confirm=TOKEN

# Local path
cp "<path>" ./media/

For a Google Drive folder URL (/drive/folders/...), the folder page IS parseable via curl. The HTML embeds file IDs as JSON inside inline scripts. Pull all of them and download each by ID:

bash
# 1. Fetch the folder page
FOLDER_URL="<the user's folder share URL>"
curl -sL "$FOLDER_URL" -o /tmp/drive-folder.html

# 2. Extract all 33-char file ID candidates from the embedded JSON
# (Drive file IDs are 28-44 chars of [A-Za-z0-9_-]; the folder ID itself is in the URL — exclude it)
FOLDER_ID=$(echo "$FOLDER_URL" | grep -oE 'folders/[^/?]+' | cut -d/ -f2)
grep -oE '"[A-Za-z0-9_-]{33}"' /tmp/drive-folder.html | sort -u | sed 's/"//g' | grep -v "^${FOLDER_ID}$" > /tmp/file-ids.txt
echo "Files found: $(wc -l < /tmp/file-ids.txt)"

# 3. Also pull the folder title (so you know the context)
grep -oE '<title>[^<]+</title>' /tmp/drive-folder.html | head -1

# 4. Download each file by ID (no auth needed for publicly shared files)
mkdir -p ./media/
i=0
while read -r FID; do
  i=$((i+1))
  curl -sL --cookie /tmp/gc --cookie-jar /tmp/gc \
    "https://drive.google.com/uc?export=download&id=$FID" \
    -o "./media/file-${i}.tmp"
  # Identify MIME type and rename appropriately
  TYPE=$(file --brief --mime-type "./media/file-${i}.tmp")
  case "$TYPE" in
    video/mp4)        mv "./media/file-${i}.tmp" "./media/file-${i}.mp4" ;;
    video/quicktime)  mv "./media/file-${i}.tmp" "./media/file-${i}.mov" ;;
    image/png)        mv "./media/file-${i}.tmp" "./media/file-${i}.png" ;;
    image/jpeg)       mv "./media/file-${i}.tmp" "./media/file-${i}.jpg" ;;
    *)                echo "  file-${i}: unknown type ($TYPE), keeping .tmp" ;;
  esac
done < /tmp/file-ids.txt
rm -f /tmp/drive-folder.html /tmp/file-ids.txt /tmp/gc
ls -la ./media/

Order matters for carousels. If you got back v1.png, v2.png, v3.png, etc. (numbered slides), sort by the numeric prefix to preserve the user's intended sequence. If filenames don't encode order, ask the user once to confirm.

If the folder is private (no ?usp=sharing or the share permissions are restricted), the HTML will be a login wall. In that case, ask the user to make it public-share OR to drop the files into the project locally.

3. Look around

bash
ls -la ./media/ 2>/dev/null

You now know: the API key state, what media you have, what's on disk. Don't enumerate any of this back at the user — proceed to the workflow.

Four invariants

These prevent real damage. Don't bypass them:

  • Approval before publish. Show the user the complete package — every platform's caption, title, hashtags, first comment, schedule, and media URLs. Wait for an explicit OK ("ship it" / "post" / "approved"). Silence is not approval.
  • Verify after publish. Zernio's 200 OK means the request was accepted, not that the platform applied your fields. Hit YouTube oEmbed and HEAD-check each platform's public URL after scheduledFor + 60s. Name any field that dropped.
  • Schedule, don't push. Use scheduledFor 2-3 minutes ahead for multi-platform. Never publishNow: true for multi-platform — it causes timeouts and duplicate posts.
  • Zernio only. Never reach for any other publishing tool. This skill uses the Zernio REST API directly.

Internalize these. Don't quote them at the user.


The workflow

Stage 1 — Intake: get the asset on disk

You should have already done this in the "First actions" section above using curl / cp. Confirm what you got:

bash
ls -la ./media/
file ./media/*    # confirm MIME types

If a download returned HTML instead of media, the source is probably gated (private Drive, login wall, expired link). Ask the user once to either share a public URL or drop the file locally — then proceed.

Stage 2 — Analyze: understand what the asset is

You can't write good captions without knowing what the asset is about. Spend a minute on this — it's the difference between generic copy and copy that lands.

For video or audio:

Extract a transcript. The user likely has a transcript-extraction tool available (extracting-transcripts skill, WhisperX, AssemblyAI). If nothing's installed, use one of these:

bash
# WhisperX (local, GPU-accelerated)
whisperx "asset.mp4" --output_format json --output_dir ./transcripts/

# faster-whisper (local CPU)
python -c "from faster_whisper import WhisperModel; m=WhisperModel('base'); segs,_=m.transcribe('asset.mp4'); [print(s.text) for s in segs]" > transcript.txt

# AssemblyAI (cloud, needs API key)
curl -X POST https://api.assemblyai.com/v2/transcript \
  -H "authorization: $ASSEMBLYAI_API_KEY" \
  -d "{\"audio_url\":\"$ASSET_URL\"}"

Read the transcript. What's the hook? What's the takeaway? What's the one sentence you'd put above the fold?

For images / carousels:

Look at each image (you have vision). Describe what you see, identify the narrative if it's a sequence (Steps / Mistakes / Before-After / Listicle), find the slide that's the strongest hook.

For URL-only posts (link share):

Read the page if it's reachable. Extract title, description, key claims.

Stage 3 — Draft: write the platform-tailored copy

Now you can draft. Each platform has different culture, character limits, and rhythm. Don't paste the same caption everywhere.

Draft for each target platform:

  • Caption / description / post body — adapted to the platform's voice and length
  • Title — for YouTube (under 100 chars)
  • Hashtags — count varies (Instagram 5-15, TikTok 3-5, LinkedIn 0-3, Twitter 1-2)
  • First comment — engagement question + CTA, for platforms that support it (YouTube, Instagram, LinkedIn, Twitter, Facebook)
  • Thumbnail — extract a strong frame from video, or use one the user provided

You don't fabricate facts. The captions reflect what the asset is actually about — drawn from the transcript, the image content, the user's stated angle. If the user said "post this with a take on X", your draft incorporates that angle. If they just said "post this," you draft from what the asset itself says.

Stage 4 — Convert: format conversions if needed

Different platforms need different shapes. Use ffmpeg.

bash
# Carousel images → 9:16 video (4 sec per slide) for TikTok / Reels / Shorts
ffmpeg -framerate 1/4 -i "slide_%02d.jpg" -c:v libx264 \
  -vf "scale=1080:1920:force_original_aspect_ratio=increase,crop=1080:1920,setsar=1" \
  -pix_fmt yuv420p -r 30 -y carousel-video.mp4

# 16:9 → 9:16 reframe (center-crop)
ffmpeg -i input.mp4 -vf "crop=ih*9/16:ih,scale=1080:1920" -c:a copy -y output-9x16.mp4

# Extract a thumbnail at a specific timestamp
ffmpeg -i video.mp4 -ss 00:00:03 -vframes 1 -q:v 2 thumbnail.jpg

# Convert PNG → JPEG (Zernio's thumbnail upload requires JPEG)
ffmpeg -i thumb.png -q:v 2 thumb.jpg

# Resize image for thumbnail spec (YouTube 1280×720)
ffmpeg -i thumb.jpg -vf "scale=1280:720" -q:v 2 thumb-1280x720.jpg

Save converted files to ./media/ in the project. Use them in the upload step.

Stage 5 — Upload: get media into Zernio

Each media file needs a presigned upload, then a PUT, then a HEAD-verify. Zernio's REST API expects lowercase filename and contentType.

bash
# 1. Presign
PRESIGN=$(curl -s -X POST "https://zernio.com/api/v1/media/presign" \
  -H "Authorization: Bearer $ZERNIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filename":"asset.mp4","contentType":"video/mp4"}')

UPLOAD_URL=$(echo "$PRESIGN" | jq -r .uploadUrl)
PUBLIC_URL=$(echo "$PRESIGN" | jq -r .publicUrl)

# 2. PUT (--tls-max 1.2 prevents TLS 1.3 bad_record_mac on macOS)
curl -X PUT "$UPLOAD_URL" -H "Content-Type: video/mp4" \
  -T "./media/asset.mp4" --tls-max 1.2 \
  -s -o /dev/null -w "%{http_code}\n"

# 3. HEAD-verify (must be 200; 404 = silent upload failure → retry)
curl -s -o /dev/null -w "%{http_code}" -I "$PUBLIC_URL"

For files over 50 MB, the presigned URL path doesn't complete reliably. Upload to external storage instead (Google Drive public share, S3, Dropbox, etc.), get a public HTTPS URL, and pass that URL into the Zernio POST body's mediaItems[].url field. The Zernio post creates without an upload step in that case. See reference/zernio-upload.md § external-storage fallback for the specifics.

Repeat for the thumbnail. Thumbnails must be JPEG — convert PNGs first.

Stage 6 — Package: build the Zernio POST body

The POST body has a precise shape. Get these right; subtle violations silently break the post.

json
{
  "content": "Top-level caption — same starting point for every platform unless overridden per-platform",
  "mediaItems": [
    {
      "url": "https://...public-uploaded-or-external-url.mp4",
      "type": "video",
      "thumbnail": "https://...public-thumbnail.jpg"
    }
  ],
  "platforms": [
    {
      "platform": "youtube",
      "accountId": "<resolved-from-GET-/accounts>",
      "platformSpecificData": {
        "title": "Video title",
        "visibility": "public",
        "tags": "claude,zernio,automation",
        "firstComment": "Engagement question + CTA link.",
        "categoryId": "28"
      }
    },
    {
      "platform": "instagram",
      "accountId": "<resolved>",
      "platformSpecificData": {
        "visibility": "public",
        "firstComment": "Follow-up engagement hook"
      },
      "customContent": "Instagram-tailored caption (overrides top-level content for this platform)"
    }
  ],
  "scheduledFor": "<ISO 8601 datetime, 2-3 min ahead>"
}

The placement rules that matter:

  • content is the top-level caption / description for every platform. Per-platform overrides go in platforms[].customContent, not in platformSpecificData.description.
  • platformSpecificData is flat — {title, tags, firstComment, ...} directly. Never {youtube: {title: ...}}.
  • tags is a comma-separated string: "a,b,c". Never an array ["a","b","c"].
  • mediaItems[].thumbnail is a plain URL string. Never {url: "..."}.
  • firstComment MUST be in the create call. It cannot be added via API after publish.
  • One media temp URL = one POST. If a post fails, re-upload before retry.

Resolve each platform's accountId at runtime:

bash
curl -s "https://zernio.com/api/v1/accounts" \
  -H "Authorization: Bearer $ZERNIO_API_KEY" \
  | jq -r '.[] | "\(.platform): \(.id)"'

If a platform you're trying to post to isn't in the response, tell the user to connect it at https://zernio.com — that's a dashboard action, not an API one.

Stage 7 — Approve: show the user the full package

Present a single block. No clipping, no summaries — the user needs to see exactly what's about to ship.

## Ready to publish — review and confirm

Platforms:    youtube, linkedin, instagram, tiktok
Schedule:     2026-05-13T18:42:00Z  (3 min from now)
Media:        ./media/asset.mp4  →  uploaded ✓
Thumbnail:    ./media/thumb.jpg  →  uploaded ✓

— YouTube —
Title:        How I built my publishing system in a week
Description:  [first 5 lines]
Tags:         claude,zernio,automation,creator,workflow
Category:     Science & Technology (28)
First comment: What would you ship first? Drop it below.

— LinkedIn —
Caption:      [first 3 lines]
First comment: Repo's in the comments.

— Instagram —
Caption:      [first 3 lines]
Hashtags:     #claudecode #zernio #automation #creator #buildinpublic
First comment: Link in bio.

— TikTok —
Caption:      [first 3 lines]
Hashtags:     #claudecode #zernio #ai

Reply "ship it" / "post" / "approved" to publish, or tell me what to change.

Wait for an explicit affirmative. If they ask for changes, apply and re-show the full block. Never ship on a partial re-approval.

Stage 8 — POST: send to Zernio

bash
curl -s -X POST "https://zernio.com/api/v1/posts" \
  -H "Authorization: Bearer $ZERNIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d "$POST_BODY_JSON"

Capture the response. For each platform, extract postId, status, and url.

Stage 9 — Verify: did the post actually land?

After scheduledFor + 60s (retry once at +120s):

bash
# Zernio echo-verify (confirms Zernio holds the fields we sent)
curl -s "https://zernio.com/api/v1/posts/$POST_ID" \
  -H "Authorization: Bearer $ZERNIO_API_KEY"

# YouTube live-verify (title + thumbnail rendered?)
curl -s "https://www.youtube.com/oembed?url=$YOUTUBE_URL&format=json" | jq

# Other platforms — HEAD the public URL
curl -s -o /dev/null -w "%{http_code}" -I "$PLATFORM_URL"

If any field dropped (YouTube routinely strips title/tags/thumbnail), name it explicitly and offer a remediation: retry, manual fix in the platform's studio, or escalate.

Stage 10 — Log: durable record on disk

Write ./posts/YYYY-MM-DD-{slug}.json:

json
{
  "slug": "how-i-built-publishing-system",
  "scheduledFor": "2026-05-13T18:42:00Z",
  "finishedAt": "2026-05-13T18:43:02Z",
  "platforms": {
    "youtube":   { "postId": "...", "url": "...", "verification": "published" },
    "linkedin":  { "postId": "...", "url": "...", "verification": "published" },
    "instagram": { "postId": "...", "url": "...", "verification": "mismatch", "droppedFields": ["thumbnail"] }
  }
}

This is the durable trail. If something goes sideways later, this is what you grep.


API key resolution

The key never lives in this skill folder or the repo. Resolution depends on runtime:

  • Claude Code CLI: check $ZERNIO_API_KEY first. If unset, source .env at the project root (set -a; source ./.env; set +a) — but only use it if the value isn't the literal placeholder zk_replace_with_your_real_key. If still unset, ask the user once (one question, friendly).
  • Claude.ai web (no shell): ask the user to paste their key at the start; hold it in conversation memory only. Never echo it back. Never write it to a file.

Get a key at https://zernio.com/dashboard/api-keys.


Style with the user

  • One question at a time. When something is genuinely missing or unclear, ask about the single most blocking thing. Never enumerate "blockers."
  • Don't quote rules at the user. Internalize them. The user doesn't want to read "Hard rule of this skill says X" — they want help.
  • Lead with what's possible. "I'll grab the files from your Drive link and start drafting captions — what angle do you want on this?" beats "I cannot proceed without a manifest."
  • You're an agent, not a form. When an asset comes in, analyze it, draft the copy, do the conversions. Don't ask the user for things you can figure out yourself.

Deep references (read when you need specifics)

FileWhen
reference/zernio-api.mdEndpoint inventory, auth, /accounts and /profiles shapes
reference/zernio-upload.mdPresign mechanics, the >50 MB external-storage fallback, gotchas
reference/zernio-post.mdFull POST body shape, all 10 field placement rules, YouTube category IDs
reference/principles.mdThe verification protocol, anti-patterns
reference/platforms.md13-platform capability matrix, media specs, cross-posting strategy
reference/platforms/{platform}.mdOne file per platform — quirks, gotchas, content rules, pre-flight checks
reference/zernio-openapi.yamlThe 17K-line canonical OpenAPI spec — source of truth if anything else disagrees

Don't preload these. Pull the one you need when the question lands.

Bundled files

The model reads these on demand while the skill is loaded. They are exposed as readable files and are never executed.

Frequently asked questions

What does the Zernio Publish AI skill do?

End-to-end social publishing through Zernio. Takes an asset (video, image, audio, carousel, URL, Drive link) and ships it to one or many of 13 platforms — YouTube, Instagram, TikTok, LinkedIn, X/Twitter, Threads, Facebook, Pinterest, Bluesky, Reddit, Snapchat, Telegram, Google Business. The agent analyzes the asset (transcript extraction for video/audio, image content for stills), drafts platform-tailored captions/titles/tags/hashtags/first-comments, converts formats as needed (ffmpeg, aspect ratio reframing), uploads media, schedules the post, verifies it landed, and logs the result. Use t...

Why use Zernio Publish on TypingMind?

Because you install it once and use it with any model. Zernio Publish is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Zernio Publish in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/Enriquemarq1/zernio-library-skills/tree/main/.claude/skills/zernio-publish. TypingMind reads its SKILL.md and bundles its files and installs it as a skill you can enable per chat.

Which AI models can use Zernio Publish?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Zernio Publish?

As many as you like. As long as a model supports skills, you can use Zernio Publish with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Zernio Publish AI skill free?

Yes. It is published on GitHub by Enriquemarq1 under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇