From 669026ab3133bd7adb8bbe99e337e8ef8df23b75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hanu=C5=A1?= Date: Thu, 2 Jul 2026 00:49:32 +0200 Subject: [PATCH] feat(create): add --list flag to print available templates Today, discovering template ids requires either visiting the actor-templates GitHub repo or running `apify create` with its interactive picker, which fails in non-TTY / agent contexts. There is no non-interactive discovery path. Add a `--list` flag to `apify create` that fetches the existing manifest (via `@apify/actor-templates`, which is already a dependency and already imported for the interactive picker) and prints one line per template in the form `\t\t`. When combined with the existing `--json` support (opted in via `enableJsonFlag`), the command emits a machine-parseable JSON object with `templates: [{id, label, category, description}, ...]`. The list path returns early before any actor-name validation or filesystem work, so it can be invoked from any directory without side effects. Co-Authored-By: Claude Opus 4.7 --- src/commands/create.ts | 46 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/src/commands/create.ts b/src/commands/create.ts index f551d4dab..34ba9e573 100644 --- a/src/commands/create.ts +++ b/src/commands/create.ts @@ -34,6 +34,7 @@ import { getJsonFileContent, isNodeVersionSupported, isPythonVersionSupported, + printJsonToStdout, setLocalConfig, setLocalEnv, } from '../lib/utils.js'; @@ -64,6 +65,14 @@ export class CreateCommand extends ApifyCommand { description: 'Create without installing dependencies (faster; run install yourself later).', command: 'apify create my-actor --template python-start --skip-dependency-install', }, + { + description: 'List available template ids (non-interactive; useful for discovery in agent contexts).', + command: 'apify create --list', + }, + { + description: 'List available templates as JSON for machine parsing.', + command: 'apify create --list --json', + }, ]; static override docsUrl = 'https://docs.apify.com/cli/docs/reference#apify-create'; @@ -92,8 +101,16 @@ export class CreateCommand extends ApifyCommand { description: 'Skip initializing a git repository in the Actor directory.', required: false, }), + list: Flags.boolean({ + description: + 'Print available template ids (name, language, description) instead of creating an Actor. ' + + 'Combine with --json for machine-parseable output. Useful for non-interactive discovery.', + required: false, + }), }; + static override enableJsonFlag = true; + static override args = { actorName: Args.string({ required: false, @@ -103,7 +120,7 @@ export class CreateCommand extends ApifyCommand { async run() { let { actorName } = this.args; - const { template: templateName, skipDependencyInstall, skipGitInit } = this.flags; + const { template: templateName, skipDependencyInstall, skipGitInit, list, json } = this.flags; // --template-archive-url is an internal, undocumented flag that's used // for testing of templates that are not yet published in the manifest @@ -116,6 +133,33 @@ export class CreateCommand extends ApifyCommand { return new Error(`Could not fetch template list from server. Cause: ${err?.message}`); }); + // --list: print available templates and exit without creating anything. + // This provides a non-interactive discovery path (agent contexts, + // non-TTY shells) for template ids that would otherwise require + // visiting the actor-templates repo or running the interactive picker. + if (list) { + const manifest = await manifestPromise; + if (manifest instanceof Error) throw manifest; + + if (json) { + printJsonToStdout({ + templates: manifest.templates.map((t) => ({ + id: t.name, + label: t.label, + category: t.category, + description: t.description, + })), + }); + return; + } + + for (const t of manifest.templates) { + // Tab-separated for easy piping: `\t\t` + simpleLog({ message: `${t.name}\t${t.category}\t${t.description}`, stdout: true }); + } + return; + } + actorName = await ensureValidActorName(actorName); const cwd = process.cwd();