Skip to content

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.


Before you publish:


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

  • Directorymy-image-resizer
    • aerostack.json // Required — metadata and config
    • index.ts // Required — your function logic
    • schema.ts // Optional — Drizzle tables
    • README.md // Recommended — shown on Hub

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
}
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

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 })
);

  1. Authenticate

    Terminal window
    aerostack login
    # Prompts: Enter your API key: ac_secret_xxxx
  2. Push to create a draft

    Terminal window
    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://app.aerostack.dev/functions/edit/<id>
  3. Publish the draft

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

    Terminal window
    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.

  4. 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: 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).

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

A minimal publishable function you can clone and modify:

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