Skip to content

sugarcraft/sugar-wishlist

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

43 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

sugar-wishlist

SugarWishlist

CI codecov Packagist Version License PHP

demo

PHP port of charmbracelet/wishlist β€” a TUI directory of SSH endpoints. Launch wishlist, pick a host, hit Enter, and the current process is replaced with ssh connecting to it.

── wishlist ──
filter:
β–Έ production  ─  deploy@prod.example.com:2222
  staging     ─  stage.example.com
  dev         ─  dev.example.com

  ↑/↓ select Β· Enter connect Β· Esc quit Β· type to filter

Install

The wishlist binary lives at bin/wishlist. Composer adds it to your global vendor/bin/ when installed as a project dependency, or you can add the repo's bin/ to your $PATH.

composer require sugarcraft/sugar-wishlist
~/.composer/vendor/bin/wishlist

Configure

wishlist looks for, in order:

  1. --config <path> (CLI flag)
  2. ~/.config/wishlist.yml
  3. ~/.config/wishlist.yaml
  4. ~/.config/wishlist.json
  5. wishlist.{yml,yaml,json} in the current directory

YAML

- name: production
  host: prod.example.com
  port: 2222
  user: deploy
  identity_file: ~/.ssh/prod-deploy

- name: staging
  host: stage.example.com
  user: deploy

- name: jumpbox
  host: bastion.example.com
  options:
    - ServerAliveInterval=30
    - ProxyJump=gw.example.com

JSON

[
  { "name": "production", "host": "prod.example.com", "port": 2222, "user": "deploy" },
  { "name": "staging",    "host": "stage.example.com" }
]

Keybindings

Key Action
↑ / k Move up
↓ / j Move down
Enter Connect to highlighted endpoint
Esc / ^C Quit without connecting
(typing) Type-to-filter; Backspace clears

Implementation

The picker is a tiny standalone widget β€” not a full SugarBits List. The lifecycle is

read config β†’ render picker β†’ read keys β†’ choose β†’ pcntl_exec(ssh, argv)

That last pcntl_exec is the critical line: it replaces the PHP process with ssh. File descriptors, environment, and the controlling tty all flow through unchanged, so the user sees a normal ssh session β€” host-key prompts, agent forwarding, MOTD, exit status, all native. We never proxy bytes; we get out of the way.

Programmatic use

use SugarCraft\Wishlist\Config;
use SugarCraft\Wishlist\Picker;
use SugarCraft\Wishlist\Launcher;

$endpoints = Config::load('/etc/wishlist.yml');
$picked    = (new Picker())->pick($endpoints);
if ($picked !== null) {
    (new Launcher())->dispatch($picked);
}

Status

Phase 9+ β€” first cut. 26 tests / 67 assertions. Endpoint, Config (JSON + flat-YAML), Picker, Launcher are all covered.

About

πŸš€ PHP port of 🧭 wishlist β€” SSH endpoint launcher: YAML/JSON shortcut directory, interactive TUI picker, full host-key & agent-forwarding fidelity.

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages