Loading repository dataβ¦
Loading repository dataβ¦
reliverse / repository
π¦βπ₯ @reliverse/rempts is a modern, type-safe toolkit for building delightful cli experiences. it's fast, flexible, and made for developer happiness. file-based commands keep things simpleβno clutter, just clean and easy workflows. this is how cli should feel.
A transparent discovery signal based on current public GitHub metadata.
This score does not audit code, security, maintainers, documentation quality, or suitability. Verify the repository and its current documentation before adoption.
sponsor β discord β repo β npm
@reliverse/rempts is a modern, type-safe toolkit for building delightful cli experiences. it's fast, flexible, and made for developer happiness. file-based commands keep things simpleβno clutter, just clean and easy workflows. this is how cli should feel.
unjs/citty and @clack/promptsinquirer/citty/commander/chalkbun dler rempts --init cmd1 cmd2)src/app/cmds.ts file (bun dler rempts)bun add @reliverse/rempts
All main prompts APIs are available from the package root:
import {
// ...prompts
inputPrompt, selectPrompt, multiselectPrompt, numberPrompt,
confirmPrompt, togglePrompt,
startPrompt, endPrompt, resultPrompt, nextStepsPrompt,
// ...hooks
createSpinner,
// ...launcher
createCli, defineCommand, defineArgs,
// ...types
// ...more
} from "@reliverse/rempts";
See
src/mod.tsfor the full list of exports.
| Prompt | Description |
|---|---|
createSpinner | Start/stop spinner |
inputPrompt | Single-line input (with mask support, e.g. for passwords) |
selectPrompt | Single-choice radio menu |
multiselectPrompt | Multi-choice checkbox menu |
numberPrompt | Type-safe number input |
confirmPrompt | Yes/No toggle |
togglePrompt | Custom on/off toggles |
resultPrompt | Show results in a styled box |
nextStepsPrompt | Show next steps in a styled list |
startPrompt/endPrompt | Makes CLI start/end flows look nice |
datePrompt | Date input with format validation |
anykeyPrompt | Wait for any keypress |
To help you migrate from the different CLI frameworks, @reliverse/rempts has some aliases for the most popular prompts.
| Prompt | Aliases |
|---|---|
createCli | runMain |
onCmdInit | setup |
onCmdExit | cleanup |
createSpinner | spinner |
selectPrompt | select |
multiselectPrompt | multiselect |
inputPrompt | text, input |
confirmPrompt | confirm |
introPrompt | intro, start |
outroPrompt | outro, end |
log | relinka |
import { relinka } from "@reliverse/relinka";
import {
startPrompt,
inputPrompt,
selectPrompt,
defineCommand,
runMain
} from "@reliverse/rempts";
async function main() {
await startPrompt({ title: "Project Setup" });
const name = await inputPrompt({
title: "What's your project name?",
defaultValue: "my-cool-project",
});
const spinner = createSpinner({
text: "Loading...",
indicator: "timer", // or "dots"
frames: ["β", "β", "β", "β"], // custom frames
delay: 80, // custom delay
onCancel: () => {
console.log("Operation cancelled");
},
cancelMessage: "Operation cancelled by user",
errorMessage: "Operation failed",
signal: abortController.signal,
}).start();
// The spinner will show:
// β Loading... [5s]
// With animated frames and timer
const framework = await selectPrompt({
title: "Pick your framework",
options: [
{ value: "next", label: "Next.js" },
{ value: "svelte", label: "SvelteKit" },
{ value: "start", label: "TanStack Start" },
],
defaultValue: "next",
});
console.log("Your result:", { name, framework });
};
await main();
Available spinner options:
| Option | Description |
|---|---|
cancelMessage | The message to display when the spinner is cancelled |
color | The color of the spinner |
delay | The delay between frames |
errorMessage | The message to display when the spinner fails |
failText | The text to display when the spinner fails |
frames | The frames to use for the spinner |
hideCursor | Whether to hide the cursor |
indicator | The indicator to use for the spinner |
onCancel | The function to call when the spinner is cancelled |
prefixText | The text to display before the spinner |
signal | The signal to use for the spinner |
silent | Whether to hide the spinner |
spinner | The spinner to use for the spinner |
successText | The text to display when the spinner succeeds |
text | The text to display next to the spinner |
Available indicator options:
| Option | Description |
|---|---|
timer | The timer indicator |
dots | The dots indicator |
Available signal options:
| Option | Description |
|---|---|
abortController.signal | The signal to use for the spinner |
Available frames options:
| Option | Description |
|---|---|
["β", "β", "β", "β"] | The frames to use for the spinner |
Available delay options:
| Option | Description |
|---|---|
80 | The delay between frames |
Available onCancel options:
| Option | Description |
|---|---|
() => { console.log("Operation cancelled"); } | The function to call when the spinner is cancelled |
Note:
runMainis now an alias forcreateCliand is still supported for backward compatibility. The newcreateCliAPI provides a more intuitive object-based configuration format.
bun add -D @reliverse/dler
bun dler rempts --init cmd1 cmd2 # creates `src/app/cmd1/cmd.ts` and `src/app/cmd2/cmd.ts` files
bun dler rempts # creates `src/app/cmds.ts` file
Important: Ensure your commands don't have await main();, await createCli();, or something like that β to prevent any unexpected behavior. Only main command should have it.
import { relinka } from "@reliverse/relinka";
import { defineCommand, createCli } from "@reliverse/rempts";
const main = defineCommand({
meta: {
name: "rempts",
version: "1.0.0",
description: "Rempts Launcher Playground CLI",
},
onCmdInit() {
relinka("success", "Setup");
},
onCmdExit() {
relinka("success", "Cleanup");
},
commands: {
build: () => import("./app/build/cmd.js").then((r) => r.default),
deploy: () => import("./app/deploy/cmd.js").then((r) => r.default),
debug: () => import("./app/debug/cmd.js").then((r) => r.default),
},
});
// New object format (recommended)
await createCli({
mainCommand: main,
fileBased: {
enable: true,
cmdsRootPath: "my-cmds", // default is `./app`
},
// Optionally disable auto-exit to handle errors manually:
autoExit: false,
});
// Legacy format (still supported)
await createCli(main, {
fileBased: {
enable: true,
cmdsRootPath: "my-cmds", // default is `./app`
},
// Optionally disable auto-exit to handle errors manually:
autoExit: false,
});
This flexibility allows you to easily build a rich, multi-command CLI with minimal boilerplate. The launcher even supports nested commands, making it simple to construct complex CLI applications.
Drop a ./src/cli/app/add/index.ts and it's live.
import { defineArgs, defineCommand } from "@reliverse/rempts";
export default defineCommand({
meta: {
name: "add",
version: "1.0.0",
description: "Add stuff to your project",
},
args: {
name: defineArgs({ // π‘ PRO TIP: use defineArgs() to get fully correct intellisense
type: "string",
required: true,
description: "Name of what to add",
}),
},
async run({ args }) {
relinka("log", "Adding:", args.name);
},
});
Supports:
arg-cmdName.{ts,js},cmdName/index.{ts,js},cmdName/cmdName-mod.{ts,js},foo/bar/baz/cmd.ts β my-cli foo bar bazHint:
bun add -D @reliverse/dlerbun dler rempts --init cmd1 cmd2 to init commands for rempts launcher's automaticallydefineCommand({
meta: { name: "cli", version: "1.0.0" },
args: {
name: { type: "string", required: true },
verbose: { type: "boolean", default: false },
animals: { type: "array", default: ["cat","dog"] },
},
async run({ args, raw }) { // or `async run(ctx)`
relinka("log", args.name, args.verbose, args.animals); // or `relinka("log", ctx.args.name, ...);`
},
});
Supports:
positional argsarray types (--tag foo --tag bar)By the way! Multi-level subcommands!
You can also nest subcommands arbitrarily deep:
app/
foo/
bar/
baz/
cmd.ts
Invoke with:
my-cli foo bar baz --some-flag
The launcher will recursively traverse subfolders for each non-flag argument, loading the deepest cmd.ts/cmd.js it finds, and passing the remaining arguments to it.
See example/launcher/app/nested and example/launcher/app/sibling folders to learn more.
When pl