MCMD short name for Meta Framework for Command. Inspired from Next.JS (Meta Framework for React.JS)
Enjoy the DX of File Based Routing for CLI development with zod validation and TypeScript support out of the box.
Install MCMD package from NPM
Or clone the ready-made template from MCMD github repository
npx create mcmd-app --name my-clibun create mcmd-app --name my-cliYou can install the MCMD skill files from this repository using the Skills CLI:
npx skills add manolo-in/mcmdThis pulls the repository skill collection (including mcmd-cli) so developers can use the same guidance in their own projects.
root
├── .mcmd
├── node_modules
│
├─┬ app
│ ├── index.ts # npx my-cli
│ ├── config.ts # config file
│ ├─┬ init
│ │ ├── something.ts # npx my-cli init something
│ │ └── index.ts # npx my-cli init
│ └── login.ts # npx my-cli login
│
├── package.json
├── .gitignore
├── README.md
├── tsconfig.json
└── tsdown.config.ts # default bundler
Don't need to import zod or Command, we'll handle everything for you.
// app/index.ts
export const options = z.object({
name: z.string(),
});
export default Command((data) => {
const { name } = data;
Console.log("Hi", name);
});
// npx my-cli --name Rajat// app/init.ts
export default () => {
// a custom console with colors and prompts support
Console.log("Done Init");
};
// npx my-cli initTranspile the code (dev mode)
npx mcmd transpileRun the CLI before converting to javascript
node ./.mcmd/cli.ts --name Rajat
# or
tsx ./.mcmd/cli.ts --name Rajat
bun run ./.mcmd/cli.ts --name RajatBuild the CLI
npx mcmd buildRun the CLI after converting to javascript
node ./dist/cli.js --name Rajat
# or
bun run ./dist/cli.js --name Rajatnpx mcmd build
# or, split the work
npx mcmd transpile
npx tsdownImportant
Make sure to have a bundler config file for tsdown before building
// tsdown.config.ts
import { defineConfig } from "tsdown";
export default defineConfig([
{
entry: ["./.mcmd/cli.ts"],
format: ["esm"],
outDir: "bin",
dts: false,
banner: {
js: "#!/usr/bin/env node",
},
},
]);npm login
npm publishbunx my-cli --name Rajat
# or
npx my-cli --name RajatExtends you tsconfig.json with mcmd/base.json
{
// tsconfig.json
"compilerOptions": {},
"extends": ["mcmd/base.json"]
}Or directly use mcmd/type in tsconfig.json
{
// tsconfig.json
"compilerOptions": {
"types": ["mcmd/type"]
}
}Or paste this code to ./type.d.ts
// Don't remove this.
// This helps for automatic type assigning for MCMD.
/// <reference types="mcmd/type" />Follow this code to get full TypeScript support
// app/index.ts
export const options = z.object({
name: z.string(),
});
export default Command<typeof options, {}>((data, beforeData) => {
const { name } = data;
Console.log("Hi", name);
});Create the file config.ts inside the app folder and paste this.
export default defineConfig({
// paste your parser config here
// eg
parser: {
string: ["bar"],
configuration: {
"boolean-negation": false,
},
},
// custom hook for before and after running the command
hook: {
// before, but after parsing the arguments
before: async (commands, data) => {
return beforeData; // access this ↴
},
// export default Command((data, beforeData) => {})
extra: async (commands, data) => {
return extraData; // access this ↴
},
after: async (commands, dataWithExtraData) => {},
},
});By default, mcmd do the transpiling and tsdown take care of final bundling.
You can customize it by bringing your own bundler like tsup or unbuild
npx mcmd transpile// tsup.config.ts
import { defineConfig } from "tsup";
export default defineConfig({
entry: ["./.mcmd/cli.ts"], // entry point of mcmd
format: ["esm"],
outDir: "bin",
dts: false,
banner: {
js: "#!/usr/bin/env node",
},
});npx tsupMCMD is built on top of some amazing libraries, you can directly use them in your code without installing them separately.