ChrysaLisp CMD App Skill
A ChrysaLisp command app is a short-lived task in cmd/ named
<name>.lisp. It takes options and paths, does work on them, and writes
results to stdout. The general ChrysaLisp disciplines (see the
chrysalisp skill, LLM.md, and docs/ai_digest/) apply on top of these
app-specific patterns.
How CMD Apps Run
CMD apps run inside the TUI or Terminal app (apps/tui/), which uses
the Pipe class from lib/task/pipe.inc:
You type bare command names — no cmd/ prefix, no .lisp
extension. Each element of the command line resolves to
cmd/<name>.lisp automatically, with its remaining words passed as
arguments.
The kernel launches each task and runs its main function (via
class/lisp/run.vp), so the app's entry point is (defun main ()).
Elements are chained into a pipeline; each element's stdout feeds
the next element's stdin, all via message-passing streams.
Task distribution binders control where each stage is placed in
the cluster (see LLM.md and docs/ai_digest/task_pipelines.md):
| (distribution): launches the next task with
`+kn_call_run`, triggering emergent load balancing. The search
starts at the previous task's node, so stages land near their
data source.
! (pinning): launches the next task with +kn_call_pin,
pinned to the exact same node as the previous task. Use it for
communication-intensive stages that should share local memory.
Example:
files obj/vp/ | grep -v apps/ | grep -v /create | grep -v /type
| trace -l
Canonical Structure
Copy cmd/template.lisp as the starting point:
(import "lib/options/options.inc")
(import "lib/task/cmd.inc")
(defq usage `(
(("-h" "--help")
"Usage: template [options] [path] ...
options:
-h --help: this help info.
-j --jobs num: max jobs per batch, default 1.
If no paths given on command line
then will take paths from stdin.")
(("-j" "--jobs") ,(opt-num 'opt_j))
))
;do the work on a file
(defun work (file)
(print "Work on file: " file))
(defun main ()
;initialize pipe details and command args, abort on error
(when (and
(defq stdio (create-stdio))
(defq opt_j 1 args (options stdio usage)))
;from args ?
(if (empty? (defq jobs (rest args)))
;no, so from stdin
(lines! (# (push jobs %0)) (io-stream 'stdin)))
(if (<= (length jobs) opt_j)
;do the work when batch size ok !
(each (const work) jobs)
;do the jobs out there, by calling myself !
(each (lambda ((job result)) (prin result))
(pipe-farm (map (# (str (first args)
" -j " opt_j
" " (slice (str %0) 1 -2)))
(partition jobs opt_j)))))))
Key Patterns
Options: The usage form is a quasiquote: the first element
pairs ("-h" "--help") with the help text; each following element
is (short long) ,(handler 'var) where handler is opt-flag,
opt-num, or opt-str. Initialize every option variable with its
default before (options stdio usage) runs — typically in the same
defq — because options only overwrites what was given on the
command line.
Args and stdin: (options stdio usage) returns the remaining
args; args[0] is the program name, so jobs are (rest args).
When no paths are given, read them from stdin line by line.
Self-invocation for parallelism: When the job batch exceeds
opt_j, farm it out by calling yourself: build each child's
command line from (first args) (the program name) plus your flags
plus the job paths, and run them with (pipe-farm (partition jobs opt_j)). Results come back as ((job result) ...); print each
result with prin.
Quoting: Job paths arrive quoted; strip the surrounding quotes
with (slice (str %0) 1 -2) when rebuilding command lines. Encode
tricky arguments (e.g., patterns) with hex-encode and decode them
on the child side (see cmd/grep.lisp).
Cooperative scheduling: Call (task-slice) periodically in
long loops (e.g., per line of a large file) so the scheduler can
run other tasks.
Output: Write results to stdout with print/prin; that is
all the pipe needs.
Examples
cmd/template.lisp: minimal starting point.
cmd/wc.lisp: multiple flags, default-all behavior, single-file
fast path.
cmd/grep.lisp: a positional pattern argument, many modes,
hex-encoded pattern passing, and both file-mode (farmed) and
stream-mode (stdin) paths.
1---2name: chrysalisp-cmd-apps3description: Use when writing or modifying ChrysaLisp command-line apps (cmd/*.lisp) — options, stdin/stdout, pipes, and pipe-farm parallelism.4---56# ChrysaLisp CMD App Skill78A ChrysaLisp command app is a short-lived task in `cmd/` named9`<name>.lisp`. It takes options and paths, does work on them, and writes10results to stdout. The general ChrysaLisp disciplines (see the11`chrysalisp` skill, `LLM.md`, and `docs/ai_digest/`) apply on top of these12app-specific patterns.1314## How CMD Apps Run1516CMD apps run inside the TUI or Terminal app (`apps/tui/`), which uses17the `Pipe` class from `lib/task/pipe.inc`:1819* You type bare command names — no `cmd/` prefix, no `.lisp`20 extension. Each element of the command line resolves to21 `cmd/<name>.lisp` automatically, with its remaining words passed as22 arguments.2324* The kernel launches each task and runs its `main` function (via25 `class/lisp/run.vp`), so the app's entry point is `(defun main ())`.2627* Elements are chained into a pipeline; each element's stdout feeds28 the next element's stdin, all via message-passing streams.2930* **Task distribution binders** control where each stage is placed in31 the cluster (see `LLM.md` and `docs/ai_digest/task_pipelines.md`):3233 * `|` (distribution): launches the next task with34 `+kn_call_run`, triggering emergent load balancing. The search35 starts at the previous task's node, so stages land near their36 data source.3738 * `!` (pinning): launches the next task with `+kn_call_pin`,39 pinned to the exact same node as the previous task. Use it for40 communication-intensive stages that should share local memory.4142* Example:4344 files obj/vp/ | grep -v apps/ | grep -v /create | grep -v /type45 | trace -l4647## Canonical Structure4849Copy `cmd/template.lisp` as the starting point:5051 (import "lib/options/options.inc")52 (import "lib/task/cmd.inc")5354 (defq usage `(55 (("-h" "--help")56 "Usage: template [options] [path] ...5758 options:59 -h --help: this help info.60 -j --jobs num: max jobs per batch, default 1.6162 If no paths given on command line63 then will take paths from stdin.")64 (("-j" "--jobs") ,(opt-num 'opt_j))65 ))6667 ;do the work on a file68 (defun work (file)69 (print "Work on file: " file))7071 (defun main ()72 ;initialize pipe details and command args, abort on error73 (when (and74 (defq stdio (create-stdio))75 (defq opt_j 1 args (options stdio usage)))76 ;from args ?77 (if (empty? (defq jobs (rest args)))78 ;no, so from stdin79 (lines! (# (push jobs %0)) (io-stream 'stdin)))80 (if (<= (length jobs) opt_j)81 ;do the work when batch size ok !82 (each (const work) jobs)83 ;do the jobs out there, by calling myself !84 (each (lambda ((job result)) (prin result))85 (pipe-farm (map (# (str (first args)86 " -j " opt_j87 " " (slice (str %0) 1 -2)))88 (partition jobs opt_j)))))))8990## Key Patterns9192* **Options:** The `usage` form is a quasiquote: the first element93 pairs `("-h" "--help")` with the help text; each following element94 is `(short long) ,(handler 'var)` where handler is `opt-flag`,95 `opt-num`, or `opt-str`. Initialize every option variable with its96 default before `(options stdio usage)` runs — typically in the same97 `defq` — because options only overwrites what was given on the98 command line.99100* **Args and stdin:** `(options stdio usage)` returns the remaining101 args; `args`[0] is the program name, so jobs are `(rest args)`.102 When no paths are given, read them from stdin line by line.103104* **Self-invocation for parallelism:** When the job batch exceeds105 `opt_j`, farm it out by calling *yourself*: build each child's106 command line from `(first args)` (the program name) plus your flags107 plus the job paths, and run them with `(pipe-farm (partition jobs108 opt_j))`. Results come back as `((job result) ...)`; print each109 result with `prin`.110111* **Quoting:** Job paths arrive quoted; strip the surrounding quotes112 with `(slice (str %0) 1 -2)` when rebuilding command lines. Encode113 tricky arguments (e.g., patterns) with `hex-encode` and decode them114 on the child side (see `cmd/grep.lisp`).115116* **Cooperative scheduling:** Call `(task-slice)` periodically in117 long loops (e.g., per line of a large file) so the scheduler can118 run other tasks.119120* **Output:** Write results to stdout with `print`/`prin`; that is121 all the pipe needs.122123## Examples124125* `cmd/template.lisp`: minimal starting point.126127* `cmd/wc.lisp`: multiple flags, default-all behavior, single-file128 fast path.129130* `cmd/grep.lisp`: a positional pattern argument, many modes,131 hex-encoded pattern passing, and both file-mode (farmed) and132 stream-mode (stdin) paths.