Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
starchild-ai-agent avatar

Community Publish

  • 3.9k installs
  • 21 repo stars
  • Updated August 2, 2026
  • starchild-ai-agent/official-skills

community-publish is a Starchild agent skill that publishes service preview URLs, lists projects on the community dashboard, and open-sources code to GitHub.

About

Community Publish is a Starchild agent skill with three independent sharing actions for projects built on the platform. publish_preview allocates a public URL on community.iamstarchild.com for a running HTTP service without automatically listing it on the dashboard. list_in_dashboard makes an existing preview discoverable in the public Project Dashboard with optional cover, tags, and description. open_source pushes project source to the Starchild community GitHub catalog with semver versioning and validation gates. Visibility is two orthogonal switches: URL access and dashboard discoverability, so agents must call get_listing_status for state questions instead of inferring from past publish calls. The publisher binding in project.yaml cross-links live demos and code repos automatically regardless of publish order. Behavioral rules require showing diffs before open_source, batching env collection on fork, and never conflating list_published_previews with list_open_source datasets. Developers use it when users want to publish, share, distribute, open-source, or check visibility of Starchild projects.

  • Three actions: publish_preview URL, list_in_dashboard discovery, open_source GitHub push.
  • URL access and dashboard listing are separate switches with get_listing_status checks.
  • publisher block in project.yaml auto cross-links live demos and code repos.
  • open_source requires project.yaml, PROJECT.md, .env.example, and validate_open_source gates.
  • publish_preview defaults listings to private until list_in_dashboard is called.

Community Publish by the numbers

  • 3,928 all-time installs (skills.sh)
  • +622 installs in the week ending Aug 2, 2026 (Skillselion tracking)
  • Ranked #6 of 248 Release Management skills by installs in the Skillselion catalog
  • Security screen: MEDIUM risk (skills.sh audit)
  • Data as of Aug 3, 2026 (Skillselion catalog sync)
At a glance

community-publish capabilities & compatibility

Capabilities
preview publish · dashboard listing · open source push · listing status · publisher crosslink · fork install · validation gates
Works with
github
Use cases
orchestration · documentation
Runs
Hosted SaaS
From the docs

What community-publish says it does

Public URL ≠ public discovery.
SKILL.md
Three independent actions
SKILL.md
npx skills add https://github.com/starchild-ai-agent/official-skills --skill community-publish

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs3.9k
repo stars21
Security audit1 / 3 scanners passed
Last updatedAugust 2, 2026
Repositorystarchild-ai-agent/official-skills

How do I share a Starchild project URL, make it discoverable, or publish the source without writing custom deploy scripts?

Publish running service previews to public URLs, list them on the community dashboard, or open-source project code to GitHub.

Who is it for?

Starchild developers sharing running services or open-sourcing tasks and scripts on the community gateway.

Skip if: Non-Starchild deployments or local development outside the Fly container where FLY_MACHINE_ID is required.

When should I use this skill?

Use when the user wants to publish, share, make public, list, distribute, deploy publicly, or open-source a Starchild project.

What you get

A live preview URL, optional dashboard listing, or versioned GitHub catalog entry with cross-links when publisher binding is set.

  • Public preview URL
  • Dashboard listing
  • Community GitHub repository push

By the numbers

  • Skill version 0.13.1 with script delivery mode
  • Exposes three independent publish actions

Files

SKILL.mdMarkdownGitHub ↗

Three independent actions

This skill handles three completely different kinds of sharing. They are NOT stages of one flow and NOT mutually exclusive — a project can be in any combination.

ActionWhat "share" means hereAudience canApplies to
publish_preview(preview_id)Allocate a public URL https://community.iamstarchild.com/{user_id}-{slug}Open the URL if they know it — point-to-point accessAny running service
list_in_dashboard(slug)Show the listing on the public Project DashboardDiscover and browse to it from the galleryA previously-published preview
open_source(project_dir)Push project source to the community GitHub repoFork the code and run their own copyAny project (task, service, script)

Critical: do NOT auto-list when publishing. publish_preview() only allocates the URL. Listing is a separate, deliberate user decision. If the user just says "publish my preview" / "公开" without mentioning the dashboard, only call publish_preview(). After it succeeds, you may mention that list_in_dashboard() exists if they want others to discover it.

Service lifecycle (start / stop / health check) lives in the preview tool. This skill only handles the share side.

---

Visibility model — read this before answering anything about who can see a project

A project's "publicness" is two orthogonal switches, not one:

SwitchOff stateOn stateFlipped by
URL accessVisiting the URL returns 404 / no serviceURL works for anyone who has the linkpublish_preview / unpublish_preview
Dashboard discoverabilityListing row has is_public=false (or doesn't exist) — invisible in the public galleryListing row has is_public=true — appears in /projectslist_in_dashboard / unlist_from_dashboard

Public URL ≠ public discovery. A preview can be URL-reachable but undiscoverable (the default state right after publish_preview), or listed but URL-down (preview stopped after being listed), or any other combination. Never collapse these into "is it public yet".

Status questions are read-only operations. Whenever the user asks anything like:

  • "is it visible / public / discoverable yet?"
  • "can other people find it?"
  • "上架了吗 / 在 dashboard 上吗 / 别人能看到吗"
  • "is the listing live?"

The authoritative answer comes ONLY from a fresh get_listing_status(slug) call. Do NOT infer the answer from "I called publish_preview earlier so it must be visible" — that's exactly the trap (publish_preview leaves is_public=false). Treat your own past actions as suggestive but never authoritative for a state question.

---

Project types — three only

typeWhat it isEligible for publish_preview()?
taskScheduled cron/interval jobNo (no HTTP port)
serviceLong-running HTTP service (dashboard, API, page)Yes — any service can be exposed at a public URL
scriptOne-shot scriptNo (no HTTP port)

Note: there is no preview type. If you encounter older docs mentioning it, treat as service.

---

Routing — match user intent to the right surface

User requests fall into two fundamentally different categories. Mixing them up is the #1 source of wrong answers in this skill.

A. Status intents — user wants to know current state

The user is asking a question about how things stand right now. The answer is data, not an action. Always reach for a read endpoint first; never answer from memory of past actions.

Sample phrasingAction
"is it visible / public / discoverable / live for others?"get_listing_status(slug)
"上架了吗 / 在 dashboard 上吗 / 别人能不能看到 / 别人能搜到吗"get_listing_status(slug)
"what URLs do I have published?" / "我发布了哪些"list_published_previews()
"what's open-sourced?" / "都有哪些开源代码"list_open_source(...)

B. Action intents — user wants to change state

Sample phrasingActionNotes
"publish" / "share" / "make public" / "公开" / "发布" (no qualifier)publish_preview(preview_id)Allocates the URL only. Listing is NOT auto-flipped.
"publish the URL" / "share the link" / "let people visit" / "公开访问"publish_preview(preview_id)Same.
"list on the dashboard" / "上架" / "show on community" / "make discoverable" / "let people find this" / "发到广场"list_in_dashboard(slug)Requires the preview to already exist.
"publish AND list" / "publish and put on dashboard" / "发布并上架"publish_preview() THEN list_in_dashboard()Two separate calls in order.
"remove from dashboard" / "下架" / "unlist" / "hide from gallery"unlist_from_dashboard(slug)Preview URL stays alive.
"open source" / "open-source the code" / "share the code" / "let others fork" / "开源代码"open_source(project_dir)Explicit code-sharing intent.
"unpublish the URL" / "take down the link"unpublish_preview(slug)Listing row stays.
"remove the open source" / "delete from GitHub"remove_open_source(slug)
"fork" / "install someone's project"fork(source)
Ambiguous after rereadingAsk one question, don't guess"Do you want it (a) just shareable by URL, (b) also discoverable on the public dashboard, or (c) also have the code open-sourced on GitHub?"

---

Cross-link via publisher: binding

When the same project has BOTH a public URL AND open-sourced code, you want them paired so the frontend renders "View Source" on the listing card and "Visit Live Demo" on the code card. This skill drives that pairing through one explicit binding in project.yaml — no name guessing, no fuzzy matching, no follow-up dialogues.

How to declare the binding

Add a publisher: block to project.yaml:

name: my-app                      # GitHub catalog slug + default for both sides
type: service
version: 1.0.0
publisher:
  code_slug: my-app               # OPTIONAL — defaults to manifest.name
  public_slug: my-app-pub         # OPTIONAL — URL suffix; defaults to code_slug

Both fields are optional. If omitted, both default to manifest.name. Set them only when you want different slugs on each side (e.g. short URL dash for code my-detailed-dashboard).

Either side can be published first

The gateway holds a pending entry until the second side arrives. No ordering requirement, no manual link step.

OrderWhat happens
open_source first → publish_preview secondopen_source records pending entry; publish_preview consumes it and links
publish_preview first → open_source secondpublish_preview records pending entry (needs publisher_code_slug arg); open_source consumes it and links
Both at once / rename laterRe-run either side with updated binding; gateway re-links

Calling publish_preview with binding

When publishing the URL FIRST and the code will follow:

publish_preview(
    preview_id="my-app-a3f1",
    slug="my-app-pub",
    publisher_code_slug="my-app",   # so future open_source(my-app) auto-links here
)

If publisher_code_slug is omitted, no pending entry is recorded — the code side will need to declare publisher.public_slug itself in project.yaml to wire the link.

Return value

Both functions return a publisher field showing what binding was sent and a hint describing the cross-link state:

{"ok": True, "url": "...", "publisher": {"code_slug": "my-app"},
 "hint": "Cross-link binding declared. If that code is already open-sourced, it's now linked. If not, the link is pending..."}

You don't need to react to the hint — it's informational. The gateway handles wiring automatically.

Manual repair (rare)

If a pairing was wired wrong (e.g. after a rename or a slug typo), use:

link_to_listing(listing_slug="2004-my-app-pub", code_slug="my-app")

This skips the binding flow and writes the link directly. Don't use this for normal publishing — fix project.yaml's publisher: block instead so the binding survives future republishes.

---

Architecture

                community.iamstarchild.com (single gateway domain)
                              │
            ┌─────────────────┴─────────────────┐
            │                                   │
   ┌────────▼─────────┐                ┌────────▼─────────┐
   │  /api/register   │                │/api/code-projects│
   │  /api/unregister │                │ /publish, /list, │
   │  /api/list       │                │ /unpublish, ...  │
   └────────┬─────────┘                └────────┬─────────┘
            │                                   │
   ┌────────▼─────────┐                ┌────────▼─────────┐
   │ DB: route table  │                │ GitHub:          │
   │ + project_       │                │ Starchild-ai-    │
   │   listings       │                │ agent/community- │
   │ + publisher_     │                │ projects         │
   │   pending_links  │                │                  │
   │                  │                │ Permanent.       │
   │ Service stays up │                │                  │
   │ as long as your  │                │                  │
   │ container runs.  │                │                  │
   └──────────────────┘                └──────────────────┘
     publish_preview()                    open_source()

publisher_pending_links is the cross-link table. Either side writes a pending row, the other side consumes it on arrival.

---

publish_preview() — public URL

publish_preview(preview_id, slug="", title="", publisher_code_slug="")

Map a running service to https://community.iamstarchild.com/{user_id}-{slug}.

  • preview_id: from preview(action='serve'). Must be status=running.
  • slug: URL suffix only (lowercase alphanumeric + hyphens, 3-50 chars). User_id prefix is added automatically — pass 'my-app', NOT '1463-my-app'.
  • title: display name for the listing.
  • publisher_code_slug: optional cross-link binding to a code project's slug. Sets up the pending entry so the eventual open_source() call auto-links.

Returns {"ok": True, "url": "...", "publisher": {...}, "hint": "..."}.

Constraints:

  • Max 20 published previews per user (gateway returns 429 over).
  • Service must be running. Stops working when the container goes down (visitors see offline page).
  • Slug stays bound to the port — stop and re-serve, the URL stays valid.
  • Only works inside the Starchild Fly container (needs FLY_MACHINE_ID).
  • Listing visibility default is `is_public=false`. A successful publish_preview allocates the URL but creates the listing row in PRIVATE state — strangers cannot discover the project on the dashboard. Discovery requires a separate list_in_dashboard() call. Do NOT tell the user "your project is now public" after only calling publish_preview — say "the URL is live" and offer list_in_dashboard as the next step if they want it discoverable.

Companions:

  • unpublish_preview(slug) — remove the public URL. Slug accepts full {user_id}-{suffix} or just suffix.
  • list_published_previews() — all currently published preview URLs for this user.

---

list_in_dashboard() — show on Project Dashboard

list_in_dashboard(slug, name=None, description="", cover_url=None, tags=None)

Make a published preview discoverable in the public Project Dashboard at https://community.iamstarchild.com/projects. Without this, the preview URL works but is invisible to anyone who doesn't already know it.

  • slug: the full slug returned by publish_preview() (i.e. {user_id}-{suffix}). The gateway's ownership check uses this exact value.
  • name: dashboard card display name. Defaults to slug.
  • description: ≤500 chars.
  • cover_url: must be on storage.googleapis.com, image.thum.io, or api.microlink.io. Other domains rejected with 400. If omitted, the gateway captures a screenshot asynchronously.
  • tags: ≤5 tags, ≤20 chars each.

Returns {"ok": True, "listing": {...}, "url": "...", "dashboard_url": "..."}.

Constraints:

  • Requires publish_preview() to have run first for the same slug — returns 404 with a clear error otherwise.
  • Idempotent: calling again with different name/tags updates the existing listing.
  • Listings created via publish_preview() start as private (not on dashboard) — list_in_dashboard() is the ONLY way to make them discoverable.

Companions:

  • unlist_from_dashboard(slug) — remove from dashboard, keep URL alive.
  • get_listing_status(slug) — read-only check: returns {ok, exists, is_public, listing}. Note: only public listings are observable through this — if the gateway returns 404, the listing is either nonexistent OR private (no way to distinguish).

---

open_source() — push code to GitHub

open_source(project_dir, version_bump="patch", message="")

Push project source to community-projects/projects/{user_id}/{slug}/ on GitHub. Versioning is delegated entirely to git history — there's no {version}/ snapshot directory and no per-type bucket above the slug. The type field inside project.yaml stays around as runtime metadata (so forks know whether to schedule, run-once, or expose a service) but no longer affects the storage path.

  • project_dir: e.g. output/projects/my-task
  • version_bump: patch | minor | major | none
  • message: commit message body describing what this version changed.

You (the agent) should always compose this based on the actual code changes you made in this session — never leave it blank if you know what changed, never ask the user to write it. Aim for one to three short lines. Don't list every file; describe the user-visible change. If the user explicitly said "just publish", use a one-line summary like "Initial publish" or "Re-publish without changes".

  • Returns {"ok": True, "github_url": ..., "version": ..., "publisher": {...}, "hint": "..."}

Commit message style — write like a normal git commit body:

✅ "Add WebSocket reconnect on dropped connections; refactor prompt builder for shared state." ✅ "Fix funding-rate sign convention; add unit test for negative-funding path." ❌ "Updated 3 files" (uninformative) ❌ "Modified src/index.html, src/main.py, project.yaml" (lists files instead of intent) ❌ "User asked to publish" (describes the request, not the change)

Companions:

  • fork(source, dest_dir=None) — install someone else's open-sourced project locally
  • source: "user_id/slug" (always pulls current state — older snapshots live in GitHub commit history)
  • For task type: registers as paused, returns next_step instructions
  • For service type: returns ready-to-serve info
  • list_open_source(type=None, tag=None, user=None, q=None) — browse the GitHub catalog
  • get_open_source(source) — fetch one project's full metadata
  • remove_open_source(slug) — delete project directory from GitHub catalog (owner only). Git history of the deletion + previous commits is preserved in the repo's commit log.
  • validate_open_source(project_dir) — pre-flight check before publishing

Project structure

Every project under output/projects/{slug}/:

project.yaml      # metadata (name, version, type, env_required, sc_proxy, publisher)
PROJECT.md        # required sections: What / Required env / How to start / Outputs / Troubleshooting
.env.example      # all env vars with placeholder values
.gitignore        # secrets blacklist
src/
  ├── run.py       # for type=task (must start: # -*- task-system: v3 -*-)
  ├── index.html   # for type=service (or app.py + frontend)
  └── main.py      # for type=script

Don't conflate the two list functions

list_published_previews() returns live URLs (preview side). list_open_source() returns open-sourced code (GitHub side). Different datasets — never quote one number to answer a question about the other.

---

Usage from a bash block

python3 - <<'EOF'
import sys
sys.path.insert(0, "/data/workspace/skills/community-publish")
from exports import (
    # Public URL
    publish_preview, unpublish_preview, list_published_previews,
    # Open source code
    open_source, remove_open_source, fork,
    list_open_source, get_open_source, validate_open_source,
    # Manual repair (rare)
    link_to_listing,
)

# Cross-linked publish: declare publisher in project.yaml first, then both
# sides auto-pair regardless of order.
print(publish_preview(preview_id="my-app-a3f1", slug="my-app",
                      publisher_code_slug="my-app"))
print(open_source("output/projects/my-app", version_bump="patch"))
EOF

---

Behavioral rules

  • Show the diff before `open_source()`. After validate_open_source, summarize what's about to be pushed (file list, version, type, tags, env_required) and ask for confirmation. Exception: explicit "publish without confirmation" or re-publish of a known good project.
  • Never auto-run setup.sh on fork. Show the command, let the user confirm.
  • Always collect env in one batch on fork. Read project's env_required, diff against workspace/.env, call request_env_input ONCE with the missing keys. Don't ask one-by-one.
  • Slug rules: lowercase alphanumeric + hyphens, 3-50 chars, no leading/trailing hyphen. Skill auto-strips duplicate {user_id}- prefix if you accidentally include it.
  • Version rules (open_source): strict semver. Re-publishing same version is rejected. New version must be > current latest.
  • Type immutability (open_source): once published as task, can't change to service later. Pick a different slug.
  • URL ≠ code: a public URL going down (container off) does NOT remove the open-source code, and vice versa. They're independent.
  • Don't manually call `link_to_listing()` in the normal flow. The publisher: binding handles cross-linking. Manual link is only for repair.

---

Common gotchas

SymptomCauseFix
publish_preview: Preview not foundWrong preview_id, or service was stoppedCheck /data/previews.json, restart with preview(action='serve')
publish_preview: 429 Too many published previewsHit 20-per-user gateway capunpublish_preview() something old first
publish_preview: FLY_MACHINE_ID not setRunning locally, not in Starchild containerURL publish only works in the production container
open_source: 400 Validation failed: env names not in .env.exampleListed MY_KEY in env_required but forgot .env.exampleAdd the missing key to .env.example
open_source: 400 Possible secret detectedSecret scanner found a real-looking API keyMove to env var; .env.example value should be your-key-here

| open_source: 400 Type cannot change after publish | Trying to switch task ↔ service ↔ script | Pick a different slug | | remove_open_source: 403 Permission denied | Trying to remove someone else's project | Only the owner can remove | | Cross-link not appearing on frontend | Binding mismatch between sides | Check both sides' slugs match the publisher: block; or use link_to_listing to repair | | Forked task doesn't run | Auto-registered as paused | Tell user: scheduled_task(action='activate', job_id={id}) |

---

References

  • lib/manifest.py — project.yaml parser/writer + semver helpers
  • lib/validate.py — local pre-publish validation (mirrors gateway-side checks)
  • lib/install.py — type-specific install handlers (task/service/script)
  • lib/gateway.py — HTTP client for /api/register (URL side) and /api/code-projects/* (code side)

Related skills

FAQ

Does publish_preview automatically list on the dashboard?

No. publish_preview only allocates the URL; list_in_dashboard is a separate deliberate call.

How do I check if others can discover my project?

Call get_listing_status(slug) because URL reachability does not imply dashboard visibility.

How do live demos link to open-source code?

Add a publisher block in project.yaml so the gateway cross-links URL and code slugs automatically.

Is Community Publish safe to install?

skills.sh reports 1 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.

Release Managementdistribution

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.