From 6bbff410203142c6aa6499a66e18e0d60e254da3 Mon Sep 17 00:00:00 2001 From: Victor Fan Date: Thu, 13 Aug 2026 16:55:30 -0700 Subject: [PATCH 1/6] kits:list --- src/commands/functions-kits-list.ts | 26 ++++++++++++++++++++++++++ src/commands/index.ts | 1 + src/functions/kits/config.ts | 10 ++++++++++ 3 files changed, 37 insertions(+) create mode 100644 src/commands/functions-kits-list.ts create mode 100644 src/functions/kits/config.ts diff --git a/src/commands/functions-kits-list.ts b/src/commands/functions-kits-list.ts new file mode 100644 index 00000000000..86c52ef32f0 --- /dev/null +++ b/src/commands/functions-kits-list.ts @@ -0,0 +1,26 @@ +import { Command } from "../command"; +import { listKitConfigs } from "../functions/kits/config"; +import { Options } from "../options"; +import { logLabeledBullet } from "../utils"; +import { logger } from "../logger"; +import * as Table from "cli-table3"; + +export const command = new Command("functions:kits:list") + .description("list all the kits that are installed in your firebase.json") + .option("--only-deployed", "unimplemented") + .action((options: Options) => { + const firebaseConfig = options.config; + const validatedConfig = firebaseConfig.src; + const kitConfigs = listKitConfigs(validatedConfig); + if (kitConfigs.length < 1) { + logLabeledBullet("kits", `there are no kits in firebase.json`); + return; + } + + const table = new Table({ head: ["Kit", "Instances"], style: { head: ["yellow"] } }); + for (const kitConfig of kitConfigs) { + const instanceIds = Object.keys(kitConfig.instances); + table.push([kitConfig.kit, instanceIds.join(", ")]); + } + logger.info(table.toString()); + }); diff --git a/src/commands/index.ts b/src/commands/index.ts index 213f9b33c84..6108b3b8a38 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -201,6 +201,7 @@ export function load(client: CLIClient): CLIClient { if (experiments.isEnabled("kits")) { client.functions.kits = {}; client.functions.kits.install = loadCommand("functions-kits-install"); + client.functions.kits.list = loadCommand("functions-kits-list"); } client.help = loadCommand("help"); client.hosting = {}; diff --git a/src/functions/kits/config.ts b/src/functions/kits/config.ts new file mode 100644 index 00000000000..8e0c74f4d15 --- /dev/null +++ b/src/functions/kits/config.ts @@ -0,0 +1,10 @@ +import { FirebaseConfig } from "../../firebaseConfig"; +import { ValidatedKitSingle, normalizeAndValidate, isKitConfig } from "../projectConfig"; + +/** + * Extracts only the Kit configs from a parsed Firebase.json. + */ +export function listKitConfigs(config: FirebaseConfig): ValidatedKitSingle[] { + const normalized = normalizeAndValidate(config.functions); + return normalized.filter((s) => isKitConfig(s)); +} From 37c63e20001c21e5ba6a947b143ab8e71d1229b0 Mon Sep 17 00:00:00 2001 From: Victor Fan Date: Thu, 13 Aug 2026 17:05:21 -0700 Subject: [PATCH 2/6] remove cli flag we dont really need --- src/commands/functions-kits-list.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/commands/functions-kits-list.ts b/src/commands/functions-kits-list.ts index 86c52ef32f0..a369568fedc 100644 --- a/src/commands/functions-kits-list.ts +++ b/src/commands/functions-kits-list.ts @@ -7,7 +7,6 @@ import * as Table from "cli-table3"; export const command = new Command("functions:kits:list") .description("list all the kits that are installed in your firebase.json") - .option("--only-deployed", "unimplemented") .action((options: Options) => { const firebaseConfig = options.config; const validatedConfig = firebaseConfig.src; From 94f1dcc0224e53d1523834604fc1a2e61d4a952e Mon Sep 17 00:00:00 2001 From: Victor Fan Date: Thu, 13 Aug 2026 17:06:51 -0700 Subject: [PATCH 3/6] use the "functons" cli prefix --- src/commands/functions-kits-list.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/functions-kits-list.ts b/src/commands/functions-kits-list.ts index a369568fedc..75e853dbd3d 100644 --- a/src/commands/functions-kits-list.ts +++ b/src/commands/functions-kits-list.ts @@ -12,7 +12,7 @@ export const command = new Command("functions:kits:list") const validatedConfig = firebaseConfig.src; const kitConfigs = listKitConfigs(validatedConfig); if (kitConfigs.length < 1) { - logLabeledBullet("kits", `there are no kits in firebase.json`); + logLabeledBullet("functions", `there are no kits in firebase.json`); return; } From ee09043ab93590f8f01c5d60b2404fe5ded20744 Mon Sep 17 00:00:00 2001 From: Victor Fan Date: Thu, 13 Aug 2026 17:08:10 -0700 Subject: [PATCH 4/6] slop --- src/commands/functions-kits-list.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/commands/functions-kits-list.ts b/src/commands/functions-kits-list.ts index 75e853dbd3d..3bd9e2fe0ee 100644 --- a/src/commands/functions-kits-list.ts +++ b/src/commands/functions-kits-list.ts @@ -3,12 +3,18 @@ import { listKitConfigs } from "../functions/kits/config"; import { Options } from "../options"; import { logLabeledBullet } from "../utils"; import { logger } from "../logger"; +import { FirebaseError } from "../error"; import * as Table from "cli-table3"; export const command = new Command("functions:kits:list") .description("list all the kits that are installed in your firebase.json") .action((options: Options) => { const firebaseConfig = options.config; + if (!firebaseConfig) { + throw new FirebaseError( + "No firebase.json found. Please run this command from within a Firebase project directory." + ); + } const validatedConfig = firebaseConfig.src; const kitConfigs = listKitConfigs(validatedConfig); if (kitConfigs.length < 1) { From dad8f0e35a3dd96aa4f6ce4ff2506e83cf704a0a Mon Sep 17 00:00:00 2001 From: Victor Fan Date: Mon, 17 Aug 2026 16:37:05 -0700 Subject: [PATCH 5/6] lint --- src/commands/functions-kits-list.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/functions-kits-list.ts b/src/commands/functions-kits-list.ts index 3bd9e2fe0ee..9a268c5d1c4 100644 --- a/src/commands/functions-kits-list.ts +++ b/src/commands/functions-kits-list.ts @@ -12,7 +12,7 @@ export const command = new Command("functions:kits:list") const firebaseConfig = options.config; if (!firebaseConfig) { throw new FirebaseError( - "No firebase.json found. Please run this command from within a Firebase project directory." + "No firebase.json found. Please run this command from within a Firebase project directory.", ); } const validatedConfig = firebaseConfig.src; From ac35e000a755459e894015d15ae94fd97d902b04 Mon Sep 17 00:00:00 2001 From: Victor Fan Date: Mon, 17 Aug 2026 16:38:51 -0700 Subject: [PATCH 6/6] use requireConfig --- src/commands/functions-kits-list.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/commands/functions-kits-list.ts b/src/commands/functions-kits-list.ts index 9a268c5d1c4..4b34fe1a768 100644 --- a/src/commands/functions-kits-list.ts +++ b/src/commands/functions-kits-list.ts @@ -1,20 +1,16 @@ +import { requireConfig } from "../requireConfig"; import { Command } from "../command"; import { listKitConfigs } from "../functions/kits/config"; import { Options } from "../options"; import { logLabeledBullet } from "../utils"; import { logger } from "../logger"; -import { FirebaseError } from "../error"; import * as Table from "cli-table3"; export const command = new Command("functions:kits:list") .description("list all the kits that are installed in your firebase.json") + .before(requireConfig) .action((options: Options) => { const firebaseConfig = options.config; - if (!firebaseConfig) { - throw new FirebaseError( - "No firebase.json found. Please run this command from within a Firebase project directory.", - ); - } const validatedConfig = firebaseConfig.src; const kitConfigs = listKitConfigs(validatedConfig); if (kitConfigs.length < 1) {