Mischief

10 / Docs

Install Command

The install line for a library, switchable between package managers, with the runner and the installer kept apart.

npx shadcn@latest add Tinkerers-Labs/mischief-ui/hold-button

Running a package and adding one are different verbs, so they come from different tables.

Installation

Copy the source into your project, or keep it behind a package.

npx shadcn@latest add Tinkerers-Labs/mischief-ui/install-command
import { InstallCommand } from "mischief-ui/install-command"
Also installs
  • lucide-react

Or paste it in yourself. The source imports the shared cn helper from @/lib/utils, so point that at your own copy.

registry/default/install-command/install-command.tsx
"use client" import * as React from "react"import { Check, Clipboard, Terminal } from "lucide-react"import { cn } from "@/lib/utils" export type PackageManager = "npm" | "pnpm" | "yarn" | "bun" /** A labelled thing to copy, when the built-in verbs do not fit. */export type InstallTab = {  id: string  label: string  value: string  /** Wrap rather than scroll, for anything that is not one line. */

Usage

export function Install() {
  return (
    <InstallCommand
      run="shadcn@latest add tabs"
      add="my-lib"
      prompt="Read the docs, then add Tabs to this project."
    />
  )
}

Running something, or adding it

The two props are two different verbs, and a block can offer either or both. run is a one-off execution -- a generator, a registry command -- and add is a dependency going into package.json. Each manager has its own word for each, and picking a manager applies to whichever verb is showing.

Managerrunadd
npmnpxnpm install
pnpmpnpm dlxpnpm add
yarnyarn dlxyarn add
bunbunx --bunbun add

Pass the arguments without the verb -- shadcn@latest add tabs, not npx shadcn@latest add tabs -- and the block builds the whole line. Choosing pnpm and then switching to the package option gives pnpm add rather than snapping back to the default.

When it is not an install

The package managers are the common case, not the only one. A block that offers a skill, a server config, and a curl call is the same thing -- a few labelled snippets and one copy button -- but none of them is npm install. Pass tabs and they replace the managers entirely.

<InstallCommand
  tabs={[
    { id: "skill", label: "skill", value: skillCommand },
    { id: "mcp", label: "mcp", value: serverConfig, wrap: true },
    { id: "curl", label: "curl", value: curlCall },
  ]}
/>
wrap suits anything that is not one line, such as a JSON block.

The agent option

prompt adds a third choice that is not a command at all: an instruction to paste into a coding agent. It sits beside the shell commands because that is now one of the ways people install things, and copying it uses the same control.

<InstallCommand
  run="shadcn@latest add tabs"
  add="mischief-ui"
  prompt={`Read ${docsUrl} and add this component to my project.`}
/>

Only the options you supply are offered, so a block with just add shows no manager row at all and no empty tabs.

API

tabsInstallTab[]Your own tabs, which replace the package managers entirely.
defaultTabstringWhich of those opens first. Defaults to the first.
runstringArguments for a one-off runner, such as shadcn@latest add tabs.
addstringPackages to add as a dependency.
promptstringAn instruction to paste into a coding agent, offered beside the commands.
managers, defaultManagerPackageManager[], PackageManagerWhich package managers to offer and which leads. Defaults to npm.
packageLabel, promptLabel, notestring, string, ReactNodeCopy for the two extra options and the line beneath.

InstallTab

idstringUnique within the set. What defaultTab names.
labelstringThe tab as shown.
valuestringWhat is displayed and copied.
wrapbooleanWrap rather than scroll, for more than one line.

Accessibility

The options are a labelled group of toggle buttons reporting their pressed state, so the current choice is announced rather than shown only by a border. Running a package and adding a dependency are separate verbs, so they come from separate tables instead of one being derived from the other by rewriting a string. Only the options you supply are rendered, and a prompt wraps rather than scrolling sideways.