← All 21 apps

CandyScriptui

🐚 CandyScriptui

Composer-installable CLI of TUI primitives

inspired by charmbracelet/gum cli shell-script one-shot

CandyScriptui code coverage

13 subcommands — choose, confirm, file, filter, format, input, join, log, pager, spin, style, table, write. Drop into a shell script and instantly get a Charm-quality interactive UX.

Install

composer require sugarcraft/candy-scriptui

Quickstart

# Apply styling.
candy-scriptui style --foreground "#ff5f87" --bold "Hello, candy!"

# Pick one item.
choice=$(candy-scriptui choose Pizza Burger Salad)

# Read a single line.
name=$(candy-scriptui input --placeholder "Your name?")

# Confirm a destructive action.
candy-scriptui confirm "Really delete $file?" && rm "$file"

# Show a spinner while running a command.
candy-scriptui spin --title "Building..." -- make build

# Fuzzy-filter a list.
git branch | candy-scriptui filter

What's in the box

styleApply Sprinkles styling to argv (or stdin) and print.
choosePick one item from a list; prints the selection to stdout.
confirmYes/no — exit code 0 on yes, 1 on no.
filterFuzzy-filter over stdin lines.
input / writeSingle-line / multi-line text input.
fileFile picker — print the selected path.
formatRender Markdown via SugarMarkdown.
pagerScroll long input through a SugarWidgets Viewport.
spinShow a spinner while running an external command.
tableRender a CSV / TSV table with rounded borders.
logLeveled logging output (debug / info / warn / error / fatal).
joinConcatenate styled strings horizontally / vertically.

Auto-discovery

CandyScriptui uses PHP attributes to auto-discover commands at runtime. Mark any class extending Symfony\Component\Console\Command\Command with #[Command] (plus a class-level #[Flag] per option) and Application::scan() registers it once the class is loaded:

namespace My\Commands;

use SugarCraft\ScriptUi\Attribute\{Command, Flag};
use Symfony\Component\Console\Command\Command as SymfonyCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

#[Command(name: 'mycmd', description: 'Does something useful.', descriptionSection: 'Longer help text.')]
#[Flag(name: 'format', short: 'f', description: 'Output format.', default: 'json')]
final class MyCommand extends SymfonyCommand
{
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $output->writeln('format=' . $input->getOption('format'));
        return self::SUCCESS;
    }
}
use SugarCraft\ScriptUi\Application;

// scan() registers the #[Command] classes that are already loaded under the
// namespace (no trailing backslash), so load them first.
class_exists(\My\Commands\MyCommand::class);

$app = new Application();
$app->scan('My\Commands');
$app->run();                 // mycmd --format yaml  →  format=yaml

New attribute types (step 06.05)

TypeNamespaceRole
CommandSugarCraft\ScriptUi\Attribute\Command#[Attribute] for auto-registering commands
FlagSugarCraft\ScriptUi\Attribute\Flag#[Attribute] for declarative CLI options
ValueEnumSugarCraft\ScriptUi\Attribute\ValueEnumConstrained enum for flag values
CommandScannerSugarCraft\ScriptUi\Discovery\CommandScannerNamespace scanner for #[Command] classes
Application::scan()SugarCraft\ScriptUi\ApplicationOpt-in discovery method

Enhanced help (step 06.06)

TypeNamespaceRole
AliasSugarCraft\ScriptUi\Attribute\Alias#[Attribute] registering CLI command aliases
ExampleSugarCraft\ScriptUi\Attribute\Example#[Attribute] adding example usage to help output
HelpFormatterSugarCraft\ScriptUi\Help\HelpFormatterRenders enhanced help from #[Alias]/#[Example] attributes
TypoSuggesterSugarCraft\ScriptUi\Help\TypoSuggesterLevenshtein distance ≤ 2 typo suggestions for unknown commands

Shell completions + version (step 06.07)

TypeNamespaceRole
BashCompletionSugarCraft\ScriptUi\Completion\BashCompletionBash completion script generator
ZshCompletionSugarCraft\ScriptUi\Completion\ZshCompletionZsh completion script generator
FishCompletionSugarCraft\ScriptUi\Completion\FishCompletionFish completion script generator
CompletionCommandSugarCraft\ScriptUi\CompletionCommandBuilt-in completion [--shell bash|zsh|fish] subcommand
Application::versionFromComposer()SugarCraft\ScriptUi\ApplicationReads version from root composer.json

CandyScriptui also respects CANDY_SCRIPTUI_* env var fallbacks — prefix any option name with CANDY_SCRIPTUI_ in uppercase to set it when no explicit CLI flag is provided.

Source & demos

Try the quickstart →

CLI Commands

CommandDescription
completionEmit shell completion script (bash · zsh · fish)
styleApply Sprinkles styling to text
choosePick one item from a list
confirmYes/no confirmation
filterFuzzy-filter stdin lines
inputRead single-line text input
writeRead multi-line text input
fileFile picker
formatRender Markdown
pagerScroll long content
spinShow spinner during command
tableRender CSV/TSV table
logLeveled logging
joinJoin styled strings

Demos.

VHS-recorded GIFs of every example shipped with the library. Regenerated automatically on every push that touches the source.

choose

choose

Pick one item from a list.
confirm

confirm

Yes/no with exit-code semantics.
input

input

Read a single line.
write

write

Multi-line text editor.
file

file

Pick a file path.
filter

filter

Fuzzy filter over stdin.
format

format

Render Markdown via SugarMarkdown.
style

style

Apply foreground / bold to argv.
table

table

Render CSV with rounded borders.
pager

pager

Scroll long input.
log

log

Leveled logging output.
spin

spin

Spinner while running a command.
join

join

Concatenate styled chunks.