Super-readable and debuggable shell pipeline command tool, styled like yaml.
- Existing shellscript is not readable, but
yomelgive us super readable code likeyaml!! - Existing shellscript is not debugable, but
yomelgive us super structured logs!!
Bellow existing cmd has two big hard point.
- existing cmd
step_num=$(\
find \
"/home/xbabu/Desktop/share/temp/exp_py_for_yomel" \
-name "*.py" \
-type "f" \
| xargs wc -l \
| sort -nr \
| head -1 \
| sed 's/[^0-9]//g' \
);\
echo "${step_num}"- existing log
what?
- stdout
Generally, nobody wants to code in shell script if they can avoid it.
We only do it because there isn't a simpler way, but it will absolutely put you through hell—whether you're writing it, reading it back later, or trying to improve it.
Because the code is extremely difficult to read as prose/text, and debug logs are not found.
yomel give us two advantage like bellow.
- cmd
step_num=$(yomel \
title "agregate py step count" \
stage "find py file" \
-cmd find \
--argFindDir "/home/xbabu/Desktop/share/temp/exp_py_for_yomel" \
--optFilterFileName name \
--valOnlyPyExtend "*.py" \
--optFilterType type \
--valFile f \
stage "count step num by each py file" \
-cmd xargs \
--argCountCmd --n "wc -l" \
stage "sort numerically in descending order" \
--log \
-cmd sort \
--optNumrically n \
--optDescendingOrder r \
stage "get only first total line" \
--log \
-cmd head \
--optOnlyFirstLine 1 \
stage "get only step num" \
--log \
-cmd sed \
--argSubstitute --s 's/[^0-9]//g' \
);\
echo "total ${step_num}"
The above code is very long.
But we can easily recognize the pipeline's purpose from the title, stage, and --opt , --val, --arg suffix description.
For a long time, I have been considering what's make a readable shell pipline.
Eventually, I realized that the key is being rich in notes. By heavily annotating it, we can reach a readable shellpipeline.
Although this approach is very simple, I am sure of its strength.
Futhermore, look at the yomel log bellow.
yomel log is a messive advantage.
When I first saw this log, All the hassle associated with shell pipelines is disapeared.
- log
- stdout
I must point out that this log flows to stderr.
So, it has no effect on stdout at all.In other words, we are free to put debug commands like echo and tee in the middle of the shell pipeline.
Thanks to yomel, we can create a super readable and debuggable environment in our shell scripts.
curl https://raw.githubusercontent.com/puutaro/yomel/refs/heads/master/install.sh | shgo install github.com/puutaro/yomel/cmd/yomel@latestyomel parses arguments sequentially from left to right. Arguments are divided into global/stage telemetry controllers, structural elements, and value/option modifiers.
These options control debugging output and stream filtering. They do not alter the data passing through the core pipeline but manage what is written to stderr.
-
title "<pipeline_title>"-
Meaning: Sets a title for the overall pipeline. When multiple stages are executed and a title is specified, it displays a distinct header banner (
YOMEL-LOG-TITLE:) showing the title and the total generated pipeline command. -
Usage: Place it at the beginning of the command (global control section).
-
-
--no-live-stdout-
Meaning: Suppresses real-time streaming of standard output (stdout) to the console while the pipeline commands run in the background.
-
Usage: Useful for muting noisy background stream outputs during execution.
-
-
--no-live-stderr-
Meaning: Suppresses real-time streaming of standard error (stderr) to the console during execution.
-
Usage: Useful for hiding intermediate progress or warning logs until the final error handling or reporting stage.
-
-
--log- Meaning: Activates the internal logging system. When this flag is present,
yomelprints detailed panel execution metrics, generated shell commands, and raw step statuses tostderr. - Usage: Place it at the very beginning of the command to apply globally, or within specific sections.
- Meaning: Activates the internal logging system. When this flag is present,
-
--gen- Meaning: Outputs the total pipeline command.
- Usage: Useful for a
dry-runto confirm the entire generated pipeline command before execution.
-
--direct- Meaning: Executes the shell pipeline directly without internal logging decoration.
- Usage: Enables faster shell pipe execution and captures real-time
stderrlogs directly.
-
--log-filter "<shell_command>"- Meaning: Attaches an asynchronous log interceptor for standard output (
stdout). The log data captured from the stage is passed to this shell command (e.g.,grep,awk,sed) via stdin before being printed. - Usage:
--log-filter "grep 'ERROR'"ensures only log lines containing "ERROR" are emitted to your console log view.
- Meaning: Attaches an asynchronous log interceptor for standard output (
-
--err-log-filter "<shell_command>"- Meaning: Attaches an asynchronous log interceptor for standard error (
stderr). This functions exactly like--log-filterbut processes error streams thrown by the executing binaries. - Usage:
--err-log-filter "awk '{print "[ERR] " \$0}'"prefixes all error outputs with a custom tag.
- Meaning: Attaches an asynchronous log interceptor for standard error (
These keywords separate different processes and define command parts.
-
stage "<stage_name>"- Meaning: Initializes a new execution boundary (a pipeline stage). All subsequent parameters (
-cmd,--opt, etc.) are assigned to this stage until a newstagekeyword appears. - Usage:
stage "fetch-data"creates a clear logical separator for documentation and logging.
- Meaning: Initializes a new execution boundary (a pipeline stage). All subsequent parameters (
-
-cmd "<binary>"- Meaning: Specifies the main executable or binary command to be run in the current stage.
- Usage:
-cmd "aws",-cmd "curl", or-cmd "docker".
-
-svc "<service_name>"- Meaning: Declares a sub-service or second-level command hierarchy. This is highly useful for modern cloud CLIs.
- Usage: In
aws s3api,s3apiis the service. Example:-svc "s3api".
-
-act "<action_name>"- Meaning: Declares the operation, verb, or action to be performed under the specified command or service.
- Usage: In
docker container run,runis the action. Example:-act "list-objects".
Modifiers specify how parameters, options, and trailing arguments are constructed and quoted. You can append an optional Alphanumeric PascalCase description suffix to --opt, --lop, --val, and --arg to document the role of each argument clearly.
-
--opt[PascalCase] "<flag>"- Meaning: Generates a short-style option flag (prefixed with a single dash
-). An optional PascalCase suffix can be appended for documentation. - Usage:
--optVerbose "v"generates-v.
- Meaning: Generates a short-style option flag (prefixed with a single dash
-
--lop[PascalCase] "<flag>"- Meaning: Generates a long-style option flag (prefixed with double dashes
--). An optional PascalCase suffix can be appended for documentation. - Usage:
--lopRegion "region"generates--region.
- Meaning: Generates a long-style option flag (prefixed with double dashes
-
--val[PascalCase]- Meaning: Declares a value associated with the preceding option (
--optor--lop). It must be immediately followed by a quote control flag (--sor--n), and can include an optional PascalCase description suffix. - Modifiers:
--val[PascalCase] --s "<string>": Encloses the value in single quotes ('value').--val[PascalCase] --n "<string>": Emits the raw value without quotes (value), ideal for numbers or unquoted tokens.
- Usage:
--lopId --valId --s "123"generates--id '123'.--lopCount --valCount --n "5"generates--count 5.
- Meaning: Declares a value associated with the preceding option (
-
--arg[PascalCase]- Meaning: Appends a standalone, positional argument to the tail end of the generated command string. It must be immediately followed by a quote control flag (
--sor--n), and can include an optional PascalCase description suffix. - Modifiers:
--arg[PascalCase] --s "<string>": Appends a single-quoted positional argument.--arg[PascalCase] --n "<string>": Appends an unquoted positional argument.
- Usage:
--argPattern --s "/pattern/d"appends'/pattern/d'.
- Meaning: Appends a standalone, positional argument to the tail end of the generated command string. It must be immediately followed by a quote control flag (
