@allternit/apps-cli installs two commands: allternit and create-allternit-app.
server.ts, src/server.ts, server.js or src/server.js, which must export default the result of defineApp(). TypeScript runs as is.
create-allternit-app
./weather. It refuses a directory that is not empty.
allternit dev
https URL; expose the port through a tunnel.
allternit test
--url it validates the manifest, runs app.lint(), starts the server on a free port, and scans it over MCP: tools/list, resources/list, and a resources/read of every ui:// View (non-empty HTML, the text/html;profile=mcp-app MIME type, the CSP). With --url it scans a server that is already running, yours or anyone’s.
Checks include: readOnlyHint and destructiveHint stated and consistent with the tool’s name, descriptions that steer the model away from other tools, every tool’s View existing, and CSP domains that are exact, minimal and https.
Exit code 1 on any error, and on warnings too with --strict.
allternit package
plugin.json, mcp.json (exactly one streamable-HTTP server), allternit.app.json and one generated skill. It refuses to package an app with lint errors, a URL that is not https, or an app name over 30 characters. The layout is the one Package your plugin describes.
allternit submit
submit reads the listing fields from allternit.submission.json:
allternit.submission.json
https privacy and terms URLs, and the same length limits as the directory form. It then scans the hosted server the package points at, and posts the submission for review. Give the token with --token or ALLTERNIT_TOKEN; it is sent only as a bearer header and never printed. --dry-run prints the payload with reviewer credentials redacted and sends nothing.
Submitting puts the listing in review. Using your own app does not wait for it. See Submit and review.