โ† All libraries

CandyCore

๐Ÿฌ CandyCore

Elm-architecture TUI runtime

port of bubbletea runtime elm-architecture react-php fibers ssh

Model / Msg / Cmd / Program. The runtime everything else builds on. Includes the cursed cell-diff renderer ported from Bubble Tea v2 โ€” meaningful SSH bandwidth savings for slow-changing UIs.

Install

composer require candycore/candy-core

Quickstart

use CandyCore\Core\{Cmd, KeyType, Model, Msg, Program};
use CandyCore\Core\Msg\KeyMsg;

final class Counter implements Model {
    public function __construct(public readonly int $count = 0) {}
    public function init(): ?\Closure { return null; }

    public function update(Msg $msg): array {
        if ($msg instanceof KeyMsg) {
            return match (true) {
                $msg->rune === 'q'              => [$this, Cmd::quit()],
                $msg->type === KeyType::Up      => [new self($this->count + 1), null],
                $msg->type === KeyType::Down    => [new self($this->count - 1), null],
                default                         => [$this, null],
            };
        }
        return [$this, null];
    }

    public function view(): string {
        return "count: $this->count\n(โ†‘/โ†“ to change, q to quit)";
    }
}

(new Program(new Counter()))->run();

What's in the box

Model interfaceThree pure methods: init(), update(Msg), view().
Cmd helpersCmd::quit(), Cmd::batch(), Cmd::send() โ€” async work scheduled, never inlined.
InputReaderStateful escape-sequence parser. Bracketed paste, mouse, function keys, OSC, DEC private modes.
Cursed rendererCell-diff rendering ported from Bubble Tea v2. โ‰ฅ15% bandwidth savings on a 50-tick test.
ReactPHP loopMirrors goroutine semantics for input, signals, render tick, command execution.
Signal handlingCtrl+C, SIGTERM, SIGWINCH (resize) all surface as Msgs in your update().

Source & demos

Try the quickstart โ†’

Demos.

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

Counter Model

Counter Model

โ†‘ / โ†“ to count, q to quit. Demonstrates the full Model / Msg / Cmd loop.
Timer

Timer

Ticking timer driven by a Cmd-scheduled tick message.