Skip to content
@yupsh

Yup Shell

yupsh

Type shell pipelines. Get typed streams.

yup> is a shell whose every command is a type-safe Go function — composed in-process, one binary, no coreutils underneath.

yup> cat access.log | grep 503 | cut -d' ' -f1 | sort | uniq -c | sort -rn | head -3
      3 203.0.113.7
      1 198.51.100.4
      1 192.168.1.10

You already know how to read that. That is the entire point.


So what is it?

yupsh (Yup Shell, as in bash, fish, and now yup) is an interactive shell built on gloo-foo, a Go framework in which every command is a typed stream transformer — a gloo.Command[[]byte, []byte] — that composes with every other one.

yupsh gathers those commands into a prompt. When you type seq 1 10 | grep -v 5 | head -n 3, yupsh does not fork seq, grep, and head and plumb file descriptors between three processes. It builds three Go values, snaps them together into one pipeline, and runs it inside its own process. The pipe character is real composition, not an operating-system trick.

The pleasant surprise is how little that changes for you. The names are the ones you know. The flags are the ones you know (wc -l, grep -v, cut -d , -f 2, and yes, even the old head -5 shorthand). Globs expand, ~ expands, quotes stop expansion, and up-arrow brings back what you typed. Muscle memory just works — it is a shell by consequence, not by imitation.

A quick taste

yup> echo hello world
hello world

yup> seq 1 10 | grep -v 5 | head -n 3
1
2
3

yup> seq 1 100 | grep 7 | wc -l
19

yup> echo HELLO WORLD | tr A-Z a-z
hello world

yup> echo hello yup | rev
puy olleh

yup> seq 1 5 | tac
5
4
3
2
1

yup> echo yup | base64
eXVw

Every stage above ran in the same process, as a typed Go command — no fork, no exec, no $PATH lookup.

Two ways to say yup

1. The shell — yupsh

One self-contained binary (about 10 MB) with the whole toolbox inside.

go install github.com/yupsh/repl/cmd/yupsh@latest
yupsh

It is interactive on a terminal (history and in-line editing) and plain-and-deterministic when you pipe a script into it:

yupsh < script.yup

2. The standalone commands — yup-*

Prefer your existing shell? Each command also ships as its own tiny CLI, backed by the very same gloo-foo command module the shell uses:

go install github.com/yupsh/yup-seq@latest
go install github.com/yupsh/yup-grep@latest
go install github.com/yupsh/yup-wc@latest

yup-seq 1 100 | yup-grep 7 | yup-wc -l
# 19

Same behavior, same flags, same --help — just invoked the classic way.

The toolbox

Type help at the prompt for the live catalogue. Commands marked source start a pipeline; everything else filters what flows through it.

Family Commands
Generate echo · emit · seq · yes (sources)
Filesystem ls · find (sources) · basename · dirname
Search & filter grep · comm · uniq
Transform tr · sed · rev · cut · paste · split · join · nl · cat · tac · head · tail · tee · xargs
Summarize & inspect wc · sort · shuf · diff · hexdump · base64 · json
Escape hatches exec · git · perl

That is 35 commands in the shell. Browse the standalone yup-* repositories for the one-command-per-binary editions.

Escape hatches, on purpose

Purity is lovely right up until you need jq or make. For those moments, three commands deliberately leave the process:

yup> echo hi | exec cat
hi
yup> echo hello | perl -p 's/l/L/g'
yup> echo x | git --version

exec runs any program on your machine, git runs your system git, and perl runs a one-liner. Everything else stays in-process.

How a line becomes a pipeline

  1. Tokenize. The line is split into words, remembering what was quoted, then split into stages on |.
  2. Expand. Unquoted ~ and globs (*, ?, […]) expand against the filesystem. A glob that matches nothing stays literal, the way POSIX intends.
  3. Translate flags. Each Unix-style flag you typed becomes the typed option the command actually takes — wc -l becomes wc.WcLines, head -n 10 becomes head.HeadLines(10), grep -v becomes grep.GrepInvert.
  4. Choose the input. A source command generates the stream; a first command with file arguments reads those files; anything else reads standard input.
  5. Run. The stages are composed into one gloo-foo pipeline and executed with a context, streaming bytes from the first stage to your terminal.

Adding a command to the shell is, for most filters, a single entry in a registry map. The heavy lifting lives in the command's own gloo-foo module.

What yupsh is not (yet)

Honesty is a feature, so here is the fine print. yupsh is a pipeline shell, not a POSIX shell. Today it does not do:

  • Redirectionecho hi > out.txt prints hi > out.txt and writes no file.
  • Variables and substitutionX=1 is an unknown command; $HOME and $(…) are passed through as literal text.
  • Command lists&& and ; are plain arguments, not separators.
  • awk and while — their gloo-foo commands take Go values (an awk program structure, a Go function) that cannot yet be built from a line of text. When awk grows a script parser, it gets wired up like everything else.

If you need those, your regular shell is one exit away — and the yup-* commands work happily inside it.

Built-ins

help · version · clear · exit / quit — and any line starting with # is a comment, so scripts can explain themselves.

The family tree

gloo-foo/framework     the typed-stream pipeline engine
        │
gloo-foo/cmd-*         one command per module: cat, grep, wc, …
        │
        ├── yupsh/repl     the interactive shell that gathers them all  →  yup>
        └── yupsh/yup-*    each command as its own standalone CLI

yupsh is where the gloo-foo commands come to be used by humans at a prompt; gloo-foo is where they come to be used by programs.

Explore

  • yup.sh — the project home, with a browser playground and the command reference
  • repl — the shell itself
  • docs.repl — usage, architecture, the command catalogue, and development notes
  • yup-* commands — the standalone CLIs
  • gloo-foo — the framework and command modules underneath

yup.
gloo-foo commands, gathered into a single-binary shell.

Popular repositories Loading

  1. docs.repl docs.repl Public

    CSS

  2. .github .github Public

    Yup Shell - CLI power and simplicity, Pure Go

  3. yup-base64 yup-base64 Public

    yup.sh CLI wrapper: base64

    Makefile

  4. yup-basename yup-basename Public

    yup.sh CLI wrapper: basename

    Makefile

  5. yup-cat yup-cat Public

    yup.sh CLI wrapper: cat

    Makefile

  6. yup-comm yup-comm Public

    yup.sh CLI wrapper: comm

    Makefile

Repositories

Showing 10 of 37 repositories
  • repl Public

    Yup Shell — the interactive REPL for the yup.sh / gloo-foo command ecosystem

    yupsh/repl's past year of commit activity
    Go 0 AGPL-3.0 0 0 0 Updated Sep 16, 2026
  • yup-yes Public

    yup.sh CLI wrapper: yes

    yupsh/yup-yes's past year of commit activity
    Makefile 0 AGPL-3.0 0 0 0 Updated Sep 16, 2026
  • yup-xargs Public

    yup.sh CLI wrapper: xargs

    yupsh/yup-xargs's past year of commit activity
    Makefile 0 AGPL-3.0 0 0 0 Updated Sep 16, 2026
  • yup-while Public

    yup.sh CLI wrapper: while

    yupsh/yup-while's past year of commit activity
    Makefile 0 AGPL-3.0 0 0 0 Updated Sep 16, 2026
  • yup-wc Public

    yup.sh CLI wrapper: wc

    yupsh/yup-wc's past year of commit activity
    Makefile 0 AGPL-3.0 0 0 0 Updated Sep 16, 2026
  • yup-uniq Public

    yup.sh CLI wrapper: uniq

    yupsh/yup-uniq's past year of commit activity
    Makefile 0 AGPL-3.0 0 0 0 Updated Sep 16, 2026
  • yup-tr Public

    yup.sh CLI wrapper: tr

    yupsh/yup-tr's past year of commit activity
    Makefile 0 AGPL-3.0 0 0 0 Updated Sep 16, 2026
  • yup-tee Public

    yup.sh CLI wrapper: tee

    yupsh/yup-tee's past year of commit activity
    Makefile 0 AGPL-3.0 0 0 0 Updated Sep 16, 2026
  • yup-tail Public

    yup.sh CLI wrapper: tail

    yupsh/yup-tail's past year of commit activity
    Makefile 0 AGPL-3.0 0 0 0 Updated Sep 16, 2026
  • yup-tac Public

    yup.sh CLI wrapper: tac

    yupsh/yup-tac's past year of commit activity
    Makefile 0 AGPL-3.0 0 0 0 Updated Sep 16, 2026

Most used topics

Loading…