Community Hub→ Via CLI (Direct Push)

Publishing Functions via CLI

The CLI lets you publish a function from your terminal using the functions subcommand. You push source code to create a draft, then publish by ID to make it live. Point the CLI at a file (and optional aerostack.json in the same directory or project root); it creates a new draft on the Aerostack Hub each time you push.


Prerequisites

Before you publish:

Account Key vs Project Key — Publishing to the community hub requires an account key (prefix ac_), not a project key. Project keys are scoped to a single project deployment.


Function Structure

Every publishable function lives in its own directory. The only required file is aerostack.json plus at least one source file.

    • Required — metadata & config
    • Required — your function logic
    • Optional — Drizzle tables
    • Recommended — shown on Hub

The aerostack.json file

This file defines your function’s identity, version, and capabilities. It is read by both the CLI and the Hub.

aerostack.json
{
  "name": "image-resizer",
  "version": "1.0.0",
  "description": "Resize and transform images on the edge using Cloudflare Workers.",
  "category": "media",
  "language": "typescript",
  "runtime": "cloudflare-worker",
  "license": "MIT",
  "tags": ["image", "media", "resize", "cdn"],
  "entrypoint": "index.ts",
  "routePath": "/api/image-resize",
  "routeExport": "imageResizerRoute",
  "npmDependencies": [],
  "envVars": ["IMAGE_MAX_WIDTH", "IMAGE_QUALITY"],
  "drizzleSchema": false
}

aerostack.json field reference

FieldTypeRequiredDescription
namestringSlug-friendly name. Becomes the Hub URL: hub.aerostack.dev/functions/you/image-resizer
versionstringSemVer string e.g. 1.0.0
descriptionstringShort description shown in search results
categorystringOne of: auth, payments, media, email, ai, database, utility, analytics, notifications, storage
languagestringtypescript or javascript
runtimestringcloudflare-worker (default)
licensestringSPDX identifier e.g. MIT, Apache-2.0
tagsstring[]Search keywords, max 10
entrypointstringPath to main source file relative to the function directory
routePathstringDefault HTTP route when installed into a project, e.g. /api/image-resize
routeExportstringNamed export from your adapter, e.g. imageResizerRoute
npmDependenciesstring[]npm packages the consumer must install
envVarsstring[]Environment variables the consumer must set
drizzleSchemabooleanSet true if you export a Drizzle table schema
⚠️

Category casing matters — Use all lowercase. The category must exactly match one of the supported values, or publishing will be rejected with a validation error.


Writing Your Function

Your index.ts should export a Hono route handler. This is the convention the CLI bundles and the Hub displays.

index.ts
import { Hono } from 'hono';
 
export const imageResizerRoute = new Hono<{ Bindings: { DB: D1Database } }>();
 
imageResizerRoute.get('/resize', async (c) => {
  const url = c.req.query('url');
  const width = parseInt(c.req.query('width') ?? '800');
 
  if (!url) {
    return c.json({ error: 'url query param required' }, 400);
  }
 
  // Your image resizing logic using Cloudflare Images API
  return c.json({
    original: url,
    resized: `${url}?width=${width}&format=webp`,
    width,
  });
});
 
imageResizerRoute.get('/health', (c) =>
  c.json({ module: 'image-resizer', ok: true })
);

Keep core.ts separate — For complex functions, split pure business logic into core.ts and keep your HTTP adapter in index.ts. This makes your function easier to test and easier for consumers to use without Hono.


Publishing Steps

Authenticate

aerostack login
# Prompts: Enter your API key: ac_secret_xxxx

Push to create a draft

aerostack functions push ./my-image-resizer/index.ts
# Or from inside the function directory:
aerostack functions push index.ts

Each push creates a new draft function. The command outputs the function ID, slug, and a link to the Admin. Save the ID — you need it to publish from the CLI.

Example output:

Pushing function 'image-resizer' to Aerostack...
Pushed successfully!
   Slug: image-resizer
   Status: draft
   Admin URL: https://admin.aerocall.ai/functions/edit/<id>

Publish the draft

Use the ID from the push output (or from My Functions in the Admin):

aerostack functions publish <id>

Alternatively, open the Admin URL from the push output, add a README and tags, and click Publish there. The function then appears on the Hub and can be installed with aerostack functions install.

Optional: Finalize in the Admin

After pushing, your function is a Draft. To add a full README and tags before going live:

  1. Go to the Admin URL from the push output (or AdminMy Functions)
  2. Open the draft and click Edit
  3. Add README, screenshots, and usage examples
  4. Click Publish — it goes live immediately

First-time vs updating

  • First time: aerostack functions push [file] creates a new draft. Then run aerostack functions publish <id> or publish from the Admin.
  • Updating an existing function: Each aerostack functions push creates a new draft (it does not update the same function by slug). To update an existing function:
    • Admin: Open the function in Admin → My Functions → Edit, change code/metadata, Save. Optionally publish again if you want a new version snapshot.
    • CI: Use the GitHub Actions or GitLab CI workflow with POST /api/community/functions/ci/publish; that endpoint upserts by slug (updates the same function).
⚠️

Version snapshots are permanent — Once a version is published, its code snapshot is preserved in the history. Consumers who installed an earlier version can still reference it. You can only push forward — you cannot overwrite an older version string.


Common Errors

ErrorCauseFix
INVALID_CATEGORYCategory not in allowed listCheck spelling and use lowercase
MISSING_ENTRYPOINTentrypoint file not foundVerify the path is relative to the function directory
EMPTY_CODEEntrypoint file is emptyAdd at least one exported function
DUPLICATE_SLUGSlug already exists under a different accountRename your function
UNAUTHORIZEDAPI key invalid or expiredRun aerostack login again
VERSION_CONFLICTVersion string already publishedBump version in aerostack.json

Full Example Project

A minimal publishable function you can clone and modify:

git clone https://github.com/aerocall/example-functions
cd example-functions/rate-limiter
aerostack publish .