mastra
Version:
cli for mastra
817 lines (806 loc) • 30.2 kB
JavaScript
#! /usr/bin/env node
import { PosthogAnalytics } from './chunk-7OXWUU2Q.js';
export { PosthogAnalytics } from './chunk-7OXWUU2Q.js';
import { DepsService, create, checkPkgJson, checkAndInstallCoreDeps, interactivePrompt, init, logger, FileService } from './chunk-DKHFKQWY.js';
export { create } from './chunk-DKHFKQWY.js';
import { Command } from 'commander';
import { config } from 'dotenv';
import { join, dirname } from 'path';
import { getServerOptions, FileService as FileService$2, getWatcherInputOptions, writeTelemetryConfig, createWatcher } from '@mastra/deployer/build';
import { Bundler } from '@mastra/deployer/bundler';
import { getDeployer, FileService as FileService$1 } from '@mastra/deployer';
import { isWebContainer } from '@webcontainer/env';
import { execa } from 'execa';
import getPort from 'get-port';
import { writeFile } from 'fs/promises';
import { fileURLToPath } from 'url';
import * as fsExtra from 'fs-extra';
import fs, { readFileSync } from 'fs';
import stripJsonComments from 'strip-json-comments';
import { spawn } from 'child_process';
var BuildBundler = class extends Bundler {
customEnvFile;
constructor(customEnvFile) {
super("Build");
this.customEnvFile = customEnvFile;
}
getEnvFiles() {
const possibleFiles = [".env.production", ".env.local", ".env"];
if (this.customEnvFile) {
possibleFiles.unshift(this.customEnvFile);
}
try {
const fileService = new FileService$2();
const envFile = fileService.getFirstExistingFile(possibleFiles);
return Promise.resolve([envFile]);
} catch (err) {
}
return Promise.resolve([]);
}
async prepare(outputDirectory) {
await super.prepare(outputDirectory);
}
async bundle(entryFile, outputDirectory, toolsPaths) {
return this._bundle(this.getEntry(), entryFile, outputDirectory, toolsPaths);
}
getEntry() {
return `
// @ts-ignore
import { evaluate } from '@mastra/core/eval';
import { AvailableHooks, registerHook } from '@mastra/core/hooks';
import { TABLE_EVALS } from '@mastra/core/storage';
import { checkEvalStorageFields } from '@mastra/core/utils';
import { mastra } from '#mastra';
import { createNodeServer } from '#server';
// @ts-ignore
await createNodeServer(mastra);
registerHook(AvailableHooks.ON_GENERATION, ({ input, output, metric, runId, agentName, instructions }) => {
evaluate({
agentName,
input,
metric,
output,
runId,
globalRunId: runId,
instructions,
});
});
if (mastra.getStorage()) {
// start storage init in the background
mastra.getStorage().init();
}
registerHook(AvailableHooks.ON_EVALUATION, async traceObject => {
const storage = mastra.getStorage();
if (storage) {
// Check for required fields
const logger = mastra?.getLogger();
const areFieldsValid = checkEvalStorageFields(traceObject, logger);
if (!areFieldsValid) return;
await storage.insert({
tableName: TABLE_EVALS,
record: {
input: traceObject.input,
output: traceObject.output,
result: JSON.stringify(traceObject.result || {}),
agent_name: traceObject.agentName,
metric_name: traceObject.metricName,
instructions: traceObject.instructions,
test_info: null,
global_run_id: traceObject.globalRunId,
run_id: traceObject.runId,
created_at: new Date().toISOString(),
},
});
}
});
`;
}
async lint(entryFile, outputDirectory, toolsPaths) {
await super.lint(entryFile, outputDirectory, toolsPaths);
}
};
async function build({
dir: dir2,
tools,
root,
env
}) {
const rootDir = root || process.cwd();
const mastraDir = dir2 ? dir2.startsWith("/") ? dir2 : join(rootDir, dir2) : join(rootDir, "src", "mastra");
const outputDirectory = join(rootDir, ".mastra");
const defaultToolsPath = join(mastraDir, "tools/**/*.{js,ts}");
const discoveredTools = [defaultToolsPath, ...tools ?? []];
try {
const fs2 = new FileService();
const mastraEntryFile = fs2.getFirstExistingFile([join(mastraDir, "index.ts"), join(mastraDir, "index.js")]);
const platformDeployer = await getDeployer(mastraEntryFile, outputDirectory);
if (!platformDeployer) {
const deployer = new BuildBundler(env);
deployer.__setLogger(logger);
await deployer.prepare(outputDirectory);
await deployer.bundle(mastraEntryFile, outputDirectory, discoveredTools);
logger.info(`Build successful, you can now deploy the .mastra/output directory to your target platform.`);
logger.info(
`To start the server, run: node --import=./.mastra/output/instrumentation.mjs .mastra/output/index.mjs`
);
return;
}
logger.info("Deployer found, preparing deployer build...");
platformDeployer.__setLogger(logger);
await platformDeployer.prepare(outputDirectory);
await platformDeployer.bundle(mastraEntryFile, outputDirectory, discoveredTools);
logger.info("You can now deploy the .mastra/output directory to your target platform.");
} catch (error) {
if (error instanceof Error) {
logger.error(`Mastra Build failed`, { error });
}
process.exit(1);
}
}
async function deploy({ dir: dir2 }) {
let mastraDir = dir2 || join(process.cwd(), "src/mastra");
try {
const outputDirectory = join(process.cwd(), ".mastra");
const fs2 = new FileService();
const mastraEntryFile = fs2.getFirstExistingFile([join(mastraDir, "index.ts"), join(mastraDir, "index.js")]);
const deployer = await getDeployer(mastraEntryFile, outputDirectory);
if (!deployer) {
logger.warn("No deployer found.");
return;
}
try {
await deployer.prepare(outputDirectory);
await deployer.bundle(mastraEntryFile, outputDirectory, []);
try {
await deployer.deploy(outputDirectory);
} catch (error) {
console.error("[Mastra Deploy] - Error deploying:", error);
}
} catch (err) {
if (err instanceof Error) {
logger.debug(`error: ${err.message}`, { error: err });
}
}
} catch (error) {
if (error instanceof Error) {
logger.debug(`error: ${error.message}`, { error });
}
logger.warn("No deployer found.");
}
}
var DevBundler = class extends Bundler {
customEnvFile;
constructor(customEnvFile) {
super("Dev");
this.customEnvFile = customEnvFile;
}
getEnvFiles() {
const possibleFiles = [".env.development", ".env.local", ".env"];
if (this.customEnvFile) {
possibleFiles.unshift(this.customEnvFile);
}
try {
const fileService = new FileService$1();
const envFile = fileService.getFirstExistingFile(possibleFiles);
return Promise.resolve([envFile]);
} catch {
}
return Promise.resolve([]);
}
async prepare(outputDirectory) {
await super.prepare(outputDirectory);
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const playgroundServePath = join(outputDirectory, this.outputDir, "playground");
await fsExtra.copy(join(dirname(__dirname), "src/playground/dist"), playgroundServePath, {
overwrite: true
});
}
async watch(entryFile, outputDirectory, toolsPaths) {
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const envFiles = await this.getEnvFiles();
const inputOptions = await getWatcherInputOptions(entryFile, "node", {
"process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV || "development")
});
const toolsInputOptions = await this.getToolsInputOptions(toolsPaths);
const outputDir = join(outputDirectory, this.outputDir);
await writeTelemetryConfig(entryFile, outputDir);
await this.writeInstrumentationFile(outputDir);
await this.writePackageJson(outputDir, /* @__PURE__ */ new Map(), {});
this.logger.info("Installing dependencies");
await this.installDependencies(outputDirectory);
this.logger.info("Done installing dependencies");
const copyPublic = this.copyPublic.bind(this);
const watcher = await createWatcher(
{
...inputOptions,
logLevel: inputOptions.logLevel === "silent" ? "warn" : inputOptions.logLevel,
onwarn: (warning) => {
if (warning.code === "CIRCULAR_DEPENDENCY") {
if (warning.ids?.[0]?.includes("node_modules")) {
return;
}
this.logger.warn(`Circular dependency found:
${warning.message.replace("Circular dependency: ", "")}`);
}
},
plugins: [
// @ts-ignore - types are good
// eslint-disable-next-line @typescript-eslint/no-misused-promises
...inputOptions.plugins,
{
name: "env-watcher",
buildStart() {
for (const envFile of envFiles) {
this.addWatchFile(envFile);
}
}
},
{
name: "public-dir-watcher",
buildStart() {
this.addWatchFile(join(dirname(entryFile), "public"));
},
buildEnd() {
return copyPublic(dirname(entryFile), outputDirectory);
}
},
{
name: "tools-watcher",
async buildEnd() {
const toolsInputPaths = Array.from(Object.keys(toolsInputOptions || {})).filter((key) => key.startsWith("tools/")).map((key) => `./${key}.mjs`);
await writeFile(join(outputDir, "tools.mjs"), `export const tools = ${JSON.stringify(toolsInputPaths)};`);
}
}
],
input: {
index: join(__dirname, "templates", "dev.entry.js"),
...toolsInputOptions
}
},
{
dir: outputDir,
sourcemap: true
}
);
this.logger.info("Starting watcher...");
return new Promise((resolve, reject) => {
const cb = (event) => {
if (event.code === "BUNDLE_END") {
this.logger.info("Bundling finished, starting server...");
watcher.off("event", cb);
resolve(watcher);
}
if (event.code === "ERROR") {
console.log(event);
this.logger.error("Bundling failed, stopping watcher...");
watcher.off("event", cb);
reject(event);
}
};
watcher.on("event", cb);
});
}
async bundle() {
}
};
// src/commands/dev/dev.ts
var currentServerProcess;
var isRestarting = false;
var ON_ERROR_MAX_RESTARTS = 3;
var startServer = async (dotMastraPath, port, env, errorRestartCount = 0) => {
let serverIsReady = false;
try {
logger.info("[Mastra Dev] - Starting server...");
const commands = [];
if (!isWebContainer()) {
const instrumentation = import.meta.resolve("@opentelemetry/instrumentation/hook.mjs");
commands.push("--import=./instrumentation.mjs", `--import=${instrumentation}`);
}
commands.push("index.mjs");
currentServerProcess = execa("node", commands, {
cwd: dotMastraPath,
env: {
NODE_ENV: "production",
...Object.fromEntries(env),
MASTRA_DEV: "true",
PORT: port.toString(),
MASTRA_DEFAULT_STORAGE_URL: `file:${join(dotMastraPath, "..", "mastra.db")}`
},
stdio: ["inherit", "inherit", "inherit", "ipc"],
reject: false
});
if (currentServerProcess?.exitCode && currentServerProcess?.exitCode !== 0) {
if (!currentServerProcess) {
throw new Error(`Server failed to start`);
}
throw new Error(
`Server failed to start with error: ${currentServerProcess.stderr || currentServerProcess.stdout}`
);
}
currentServerProcess.on("message", async (message) => {
if (message?.type === "server-ready") {
serverIsReady = true;
try {
await fetch(`http://localhost:${port}/__refresh`, {
method: "POST",
headers: {
"Content-Type": "application/json"
}
});
} catch {
await new Promise((resolve) => setTimeout(resolve, 1500));
try {
await fetch(`http://localhost:${port}/__refresh`, {
method: "POST",
headers: {
"Content-Type": "application/json"
}
});
} catch {
}
}
}
});
} catch (err) {
const execaError = err;
if (execaError.stderr) logger.error("Server error output:", { stderr: execaError.stderr });
if (execaError.stdout) logger.debug("Server output:", { stdout: execaError.stdout });
if (!serverIsReady) {
throw err;
}
setTimeout(() => {
if (!isRestarting) {
errorRestartCount++;
if (errorRestartCount > ON_ERROR_MAX_RESTARTS) {
logger.error(`Server failed to start after ${ON_ERROR_MAX_RESTARTS} error attempts. Giving up.`);
process.exit(1);
}
logger.error(
`Attempting to restart server after error... (Attempt ${errorRestartCount}/${ON_ERROR_MAX_RESTARTS})`
);
startServer(dotMastraPath, port, env, errorRestartCount);
}
}, 1e3);
}
};
async function rebundleAndRestart(dotMastraPath, port, bundler) {
if (isRestarting) {
return;
}
isRestarting = true;
try {
if (currentServerProcess) {
logger.debug("Stopping current server...");
currentServerProcess.kill("SIGINT");
}
const env = await bundler.loadEnvVars();
await startServer(join(dotMastraPath, "output"), port, env);
} finally {
isRestarting = false;
}
}
async function dev({
port,
dir: dir2,
root,
tools,
env
}) {
const rootDir = root || process.cwd();
const mastraDir = dir2 ? dir2.startsWith("/") ? dir2 : join(process.cwd(), dir2) : join(process.cwd(), "src", "mastra");
const dotMastraPath = join(rootDir, ".mastra");
const defaultToolsPath = join(mastraDir, "tools/**/*.{js,ts}");
const discoveredTools = [defaultToolsPath, ...tools || []];
const fileService = new FileService$1();
const entryFile = fileService.getFirstExistingFile([join(mastraDir, "index.ts"), join(mastraDir, "index.js")]);
const bundler = new DevBundler(env);
bundler.__setLogger(logger);
await bundler.prepare(dotMastraPath);
const watcher = await bundler.watch(entryFile, dotMastraPath, discoveredTools);
const loadedEnv = await bundler.loadEnvVars();
const serverOptions = await getServerOptions(entryFile, join(dotMastraPath, "output"));
let portToUse = port ?? serverOptions?.port ?? process.env.PORT;
if (!portToUse || isNaN(Number(portToUse))) {
const portList = Array.from({ length: 21 }, (_, i) => 4111 + i);
portToUse = String(
await getPort({
port: portList
})
);
}
await startServer(join(dotMastraPath, "output"), Number(portToUse), loadedEnv);
watcher.on("event", (event) => {
if (event.code === "BUNDLE_END") {
logger.info("[Mastra Dev] - Bundling finished, restarting server...");
rebundleAndRestart(dotMastraPath, Number(portToUse), bundler);
}
});
process.on("SIGINT", () => {
logger.info("[Mastra Dev] - Stopping server...");
if (currentServerProcess) {
currentServerProcess.kill();
}
watcher.close().catch(() => {
}).finally(() => {
process.exit(0);
});
});
}
// src/commands/lint/rules/mastraCoreRule.ts
var mastraCoreRule = {
name: "mastra-core",
description: "Checks if @mastra/core is installed",
async run(context) {
const hasCore = context.mastraPackages.some((pkg) => pkg.name === "@mastra/core");
if (!hasCore) {
logger.error("@mastra/core is not installed. This package is required for Mastra to work properly.");
return false;
}
return true;
}
};
function readNextConfig(dir) {
const nextConfigPath = join(dir, "next.config.js");
try {
const nextConfigContent = readFileSync(nextConfigPath, "utf-8");
const configMatch = nextConfigContent.match(/const nextConfig = ({[\s\S]*?});/);
if (!configMatch?.[1]) {
return null;
}
const configStr = configMatch[1].replace(/\n/g, "").replace(/\s+/g, " ");
return eval(`(${configStr})`);
} catch {
return null;
}
}
function isNextJsProject(dir2) {
const nextConfigPath2 = join(dir2, "next.config.js");
try {
readFileSync(nextConfigPath2, "utf-8");
return true;
} catch {
return false;
}
}
var nextConfigRule = {
name: "next-config",
description: "Checks if Next.js config is properly configured for Mastra packages",
async run(context) {
if (!isNextJsProject(context.rootDir)) {
return true;
}
const nextConfig = readNextConfig(context.rootDir);
if (!nextConfig) {
return false;
}
const serverExternals = nextConfig.serverExternalPackages || [];
const hasMastraExternals = serverExternals.some(
(pkg) => pkg === "@mastra/*" || pkg === "@mastra/core" || pkg.startsWith("@mastra/")
);
if (!hasMastraExternals) {
logger.error("next.config.js is missing Mastra packages in serverExternalPackages");
logger.error("Please add the following to your next.config.js:");
logger.error(' serverExternalPackages: ["@mastra/*"],');
return false;
}
logger.info("Next.js config is properly configured for Mastra packages");
return true;
}
};
function readTsConfig(dir2) {
const tsConfigPath = join(dir2, "tsconfig.json");
try {
const tsConfigContent = readFileSync(tsConfigPath, "utf-8");
const cleanTsConfigContent = stripJsonComments(tsConfigContent);
return JSON.parse(cleanTsConfigContent);
} catch {
return null;
}
}
var tsConfigRule = {
name: "ts-config",
description: "Checks if TypeScript config is properly configured for Mastra packages",
async run(context) {
const tsConfig = readTsConfig(context.rootDir);
if (!tsConfig) {
logger.warn("No tsconfig.json found. This might cause issues with Mastra packages.");
return true;
}
const { module, moduleResolution } = tsConfig.compilerOptions || {};
const isValidConfig = moduleResolution === "bundler" || module === "CommonJS";
if (!isValidConfig) {
logger.error("tsconfig.json has invalid configuration");
logger.error("Please set either:");
logger.error(' "compilerOptions": {');
logger.error(' "moduleResolution": "bundler"');
logger.error(" }");
logger.error("or");
logger.error(' "compilerOptions": {');
logger.error(' "module": "CommonJS"');
logger.error(" }");
logger.error("For the recommended TypeScript configuration, see:");
logger.error("https://mastra.ai/en/docs/getting-started/installation#initialize-typescript");
return false;
}
logger.info("TypeScript config is properly configured for Mastra packages");
return true;
}
};
// src/commands/lint/rules/index.ts
var rules = [nextConfigRule, tsConfigRule, mastraCoreRule];
// src/commands/lint/index.ts
function readPackageJson(dir2) {
const packageJsonPath = join(dir2, "package.json");
try {
const packageJsonContent = readFileSync(packageJsonPath, "utf-8");
return JSON.parse(packageJsonContent);
} catch (error) {
if (error instanceof Error) {
logger.error(`Failed to read package.json: ${error.message}`);
}
throw error;
}
}
function getMastraPackages(packageJson) {
const allDependencies = {
...packageJson.dependencies,
...packageJson.devDependencies
};
const mastraPackages = Object.entries(allDependencies).filter(
([name]) => name.startsWith("@mastra/") || name === "mastra"
);
return mastraPackages.map(([name, version2]) => ({
name,
version: version2,
isAlpha: version2.includes("alpha")
}));
}
async function lint({ dir: dir2, root, tools }) {
try {
const rootDir = root || process.cwd();
const mastraDir = dir2 ? dir2.startsWith("/") ? dir2 : join(process.cwd(), dir2) : join(process.cwd(), "src", "mastra");
const outputDirectory = join(rootDir, ".mastra");
const defaultToolsPath = join(mastraDir, "tools");
const discoveredTools = [defaultToolsPath, ...tools ?? []];
const packageJson = readPackageJson(rootDir);
const mastraPackages = getMastraPackages(packageJson);
const context = {
rootDir,
mastraDir,
outputDirectory,
discoveredTools,
packageJson,
mastraPackages
};
const results = await Promise.all(rules.map((rule) => rule.run(context)));
const allRulesPassed = results.every((result) => result);
if (allRulesPassed) {
const fileService = new FileService();
const mastraEntryFile = fileService.getFirstExistingFile([
join(mastraDir, "index.ts"),
join(mastraDir, "index.js")
]);
const platformDeployer = await getDeployer(mastraEntryFile, outputDirectory);
if (!platformDeployer) {
const deployer = new BuildBundler();
await deployer.lint(mastraEntryFile, outputDirectory, discoveredTools);
} else {
await platformDeployer.lint(mastraEntryFile, outputDirectory, discoveredTools);
}
}
return allRulesPassed;
} catch (error) {
if (error instanceof Error) {
logger.error(`Lint check failed: ${error.message}`);
}
return false;
}
}
async function start(options = {}) {
const outputDir = options.dir || ".mastra/output";
const telemetry = options.telemetry ?? true;
try {
const outputPath = join(process.cwd(), outputDir);
if (!fs.existsSync(outputPath)) {
throw new Error(`Output directory ${outputPath} does not exist`);
}
const commands = [];
if (telemetry && !isWebContainer()) {
const instrumentation = "@opentelemetry/instrumentation/hook.mjs";
commands.push("--import=./instrumentation.mjs", `--import=${instrumentation}`);
}
commands.push("index.mjs");
const server = spawn("node", commands, {
cwd: outputPath,
stdio: "inherit",
env: {
...process.env,
NODE_ENV: "production"
}
});
server.on("error", (err) => {
logger.error(`Failed to start server: ${err.message}`);
process.exit(1);
});
process.on("SIGINT", () => {
server.kill("SIGINT");
process.exit(0);
});
process.on("SIGTERM", () => {
server.kill("SIGTERM");
process.exit(0);
});
} catch (error) {
logger.error(`Failed to start Mastra server: ${error.message}`);
process.exit(1);
}
}
// src/index.ts
var depsService = new DepsService();
var version = await depsService.getPackageVersion();
var analytics = new PosthogAnalytics({
apiKey: "phc_SBLpZVAB6jmHOct9CABq3PF0Yn5FU3G2FgT4xUr2XrT",
host: "https://us.posthog.com",
version
});
var program = new Command();
var origin = process.env.MASTRA_ANALYTICS_ORIGIN;
program.version(`${version}`, "-v, --version").description(`Mastra CLI ${version}`).action(() => {
try {
analytics.trackCommand({
command: "version",
origin
});
console.log(`Mastra CLI: ${version}`);
} catch {
}
});
program.command("create [project-name]").description("Create a new Mastra project").option("--default", "Quick start with defaults(src, OpenAI, examples)").option("-c, --components <components>", "Comma-separated list of components (agents, tools, workflows)").option("-l, --llm <model-provider>", "Default model provider (openai, anthropic, groq, google, or cerebras))").option("-k, --llm-api-key <api-key>", "API key for the model provider").option("-e, --example", "Include example code").option("-n, --no-example", "Do not include example code").option("-t, --timeout [timeout]", "Configurable timeout for package installation, defaults to 60000 ms").option("-d, --dir <directory>", "Target directory for Mastra source code (default: src/)").option(
"-p, --project-name <string>",
"Project name that will be used in package.json and as the project directory name."
).option("-m, --mcp <editor>", "MCP Server for code editor (cursor, cursor-global, windsurf, vscode)").action(async (projectNameArg, args) => {
const projectName = projectNameArg || args.projectName;
await analytics.trackCommandExecution({
command: "create",
args: { ...args, projectName },
execution: async () => {
const timeout = args?.timeout ? args?.timeout === true ? 6e4 : parseInt(args?.timeout, 10) : void 0;
if (args.default) {
await create({
components: ["agents", "tools", "workflows"],
llmProvider: "openai",
addExample: true,
timeout,
mcpServer: args.mcp
});
return;
}
await create({
components: args.components ? args.components.split(",") : [],
llmProvider: args.llm,
addExample: args.example,
llmApiKey: args["llm-api-key"],
timeout,
projectName,
directory: args.dir,
mcpServer: args.mcp
});
},
origin
});
});
program.command("init").description("Initialize Mastra in your project").option("--default", "Quick start with defaults(src, OpenAI, examples)").option("-d, --dir <directory>", "Directory for Mastra files to (defaults to src/)").option("-c, --components <components>", "Comma-separated list of components (agents, tools, workflows)").option("-l, --llm <model-provider>", "Default model provider (openai, anthropic, groq, google or cerebras))").option("-k, --llm-api-key <api-key>", "API key for the model provider").option("-e, --example", "Include example code").option("-n, --no-example", "Do not include example code").option("-m, --mcp <editor>", "MCP Server for code editor (cursor, cursor-global, windsurf, vscode)").action(async (args) => {
await analytics.trackCommandExecution({
command: "init",
args,
execution: async () => {
await checkPkgJson();
await checkAndInstallCoreDeps(args?.example || args?.default);
if (!Object.keys(args).length) {
const result = await interactivePrompt();
await init({
...result,
llmApiKey: result?.llmApiKey,
components: ["agents", "tools", "workflows"],
addExample: true
});
return;
}
if (args?.default) {
await init({
directory: "src/",
components: ["agents", "tools", "workflows"],
llmProvider: "openai",
addExample: true,
configureEditorWithDocsMCP: args.mcp
});
return;
}
const componentsArr = args.components ? args.components.split(",") : [];
await init({
directory: args.dir,
components: componentsArr,
llmProvider: args.llm,
addExample: args.example,
llmApiKey: args["llm-api-key"],
configureEditorWithDocsMCP: args.mcp
});
return;
},
origin
});
});
program.command("lint").description("Lint your Mastra project").option("-d, --dir <path>", "Path to your Mastra folder").option("-r, --root <path>", "Path to your root folder").option("-t, --tools <toolsDirs>", "Comma-separated list of paths to tool files to include").action(async (args) => {
await analytics.trackCommandExecution({
command: "lint",
args,
execution: async () => {
await lint({ dir: args.dir, root: args.root, tools: args.tools ? args.tools.split(",") : [] });
},
origin
});
});
program.command("dev").description("Start mastra server").option("-d, --dir <dir>", "Path to your mastra folder").option("-r, --root <root>", "Path to your root folder").option("-t, --tools <toolsDirs>", "Comma-separated list of paths to tool files to include").option("-p, --port <port>", "deprecated: Port number for the development server (defaults to 4111)").option("-e, --env <env>", "Custom env file to include in the dev server").action((args) => {
analytics.trackCommand({
command: "dev",
origin
});
if (args?.port) {
logger.warn("The --port option is deprecated. Use the server key in the Mastra instance instead.");
}
dev({
port: args?.port ? parseInt(args.port) : null,
dir: args?.dir,
root: args?.root,
tools: args?.tools ? args.tools.split(",") : [],
env: args?.env
}).catch((err) => {
logger.error(err.message);
});
});
program.command("build").description("Build your Mastra project").option("-d, --dir <path>", "Path to your Mastra Folder").option("-r, --root <path>", "Path to your root folder").option("-t, --tools <toolsDirs>", "Comma-separated list of paths to tool files to include").option("-e, --env <env>", "Custom env file to include in the build").action(async (args) => {
await analytics.trackCommandExecution({
command: "mastra build",
args,
execution: async () => {
await build({
dir: args?.dir,
root: args?.root,
tools: args?.tools ? args.tools.split(",") : [],
env: args?.env
});
},
origin
});
});
program.command("deploy").description("Deploy your Mastra project").option("-d, --dir <path>", "Path to directory").action(async (args) => {
config({ path: [".env", ".env.production"] });
await analytics.trackCommandExecution({
command: "mastra deploy",
args,
execution: async () => {
logger.warn(`DEPRECATED: The deploy command is deprecated.
Please use the mastra build command instead.
Then deploy .mastra/output to your target platform.
`);
await deploy({ dir: args.dir });
},
origin
});
});
program.command("start").description("Start your built Mastra application").option("-d, --dir <path>", "Path to your built Mastra output directory (default: .mastra/output)").option("-nt, --no-telemetry", "Disable telemetry on start").action(async (args) => {
await analytics.trackCommandExecution({
command: "start",
args,
execution: async () => {
await start({
dir: args.dir,
telemetry: !args.noTelemetry
});
},
origin
});
});
program.parse(process.argv);