Friendly CLI: a natural-language front-end for PatLang automation
The six self-hosted dev tools described a pattern: notice a recurring
annoyance in the PatLang workflow, build a small self-hosted tool for it, verify it against the real codebase,
and usually find a real bug along the way. Friendly CLI is that pattern applied to the user
experience of PatLang itself. It is a domain-specific layer that lets a novice write automation scripts in
plain English-like sentences — convert all md files in "docs" to docx — and have them
expanded, compiled, and executed by the same self-hosted compiler that builds PatLang's own standard library.
Friendly CLI lives under friendly_cli/ in the PatLang repository. Every file in it is PatLang,
compiled by PatLang, following the project's own rule about itself. It is not a toy: it shells out to real
system tools (Pandoc, PowerShell, Ollama), persists learned performance models to disk, discovers tools on
the system PATH, and in one experimental branch can ask a local LLM to synthesize a missing
function it needs — then write a BDD spec, compile the result with patc1.exe, and verify
the contract before registering the new action.
How it fits together
Friendly CLI is a pipeline of four cooperating layers, each written in PatLang and each building on the one below it:
Layer 1 — DSL syntax packs
The dsl/ directory contains syntax blocks that define natural-language rules for
specific domains. Each rule maps a sentence shape to a PatLang function call. For example, in
dsl/file_ops.patlang:
syntax FileOpsDSL {
trigger: Keyword("do_files");
tokens {
Word(w) = regex("[a-zA-Z0-9_.-]+", w);
StrLit(s) = regex("\"[^\"]*\"", s);
}
rule ConvertAllRule {
expect Symbol("convert");
expect Symbol("all");
let ext = expect Word;
expect Symbol("files");
expect Symbol("in");
let folder = expect StrLit;
expect Symbol("to");
let target = expect Word;
return batch_convert_files(ext, folder, target);
}
# ... copy and delete rules follow the same pattern
}
A user writes:
do_files {
convert all md files in "docs" to docx
copy all txt files in "notes" to "backup"
delete all tmp files in "cache"
}
and the syntax pack expands each line into the corresponding PatLang call. The do_goals trigger
in dsl/goal_ops.patlang works the same way for high-level goal statements like
make pdfs from markdown in docs.
Layer 2 — the action library
lib/actions.patlang provides the concrete functions that the DSL rules call: batch file
conversion (via Pandoc), batch copy, batch delete, path manipulation, and format normalization. These are
the "verbs" of the system — real, working functions that shell out to native tools and verify their
results with Design-by-Contract preconditions and postconditions.
Layer 3 — the smart reasoning engine
lib/smart_engine.patlang is where Friendly CLI becomes more than a macro expander. It implements a
Goal-Oriented Action Planning (GOAP)
engine:
- Actions are registered with preconditions and effects (e.g.,
act_md_to_docxrequireshas_mdand produceshas_docx). - Rules assert initial state facts (e.g.,
rule_add("has_md", ["docs"])). - Planning uses a backward-chaining solver to compute the action sequence that reaches a
target state (e.g.,
archive_backuprequireshas_pdf, which requireshas_docx, which requireshas_md). - Execution runs the planned actions in order, with each action bound to real PatLang code that performs the work.
When a user writes make pdfs from markdown in docs followed by archive the pdfs into
backup.zip, the GOAP engine automatically discovers the chain: convert md → docx, convert docx
→ pdf, archive pdfs into zip — and executes it end to end.
Layer 4 — adaptive performance model
Every action is timed. lib/adaptive_predictor.patlang and
lib/perf_database.patlang implement persistent linear regression models that learn the
relationship between input size (lines of code, number of files) and execution time. Before running a plan,
the engine predicts the total duration; after running, it updates the model via gradient descent and logs
the result to a SQL-style performance database on disk.
[REASONING ENGINE] Estimated total plan execution time: 12450 ms
[SMART GOAP EXECUTING] Step 1: Converting 2 Markdown files (Estimated: 5000 ms)...
-> Actually took: 4830 ms
[DATABASE UPDATE] Task: pandoc | New w: 32.5 ms/unit | Bias: 4980.0 ms
The goal preprocessor
lib/goal_preprocessor.patlang bridges the gap between human-friendly input and the DSL syntax
packs. It transforms block syntax like:
goal:
make pdfs from markdown in docs
archive the pdfs into backup.zip
into the do_goals { ... } wrapper that the syntax pack expects. This means a novice never needs
to remember curly braces or function names — they just write what they want, in sentences, and the
preprocessor handles the boilerplate.
Verification by BDD
Every capability in Friendly CLI is verified by a
PatLang BDD spec. The test_*_spec.patlang files use the
native Gherkin framework (lib/test.patlang) to assert that:
- The file operations DSL correctly converts, copies, and deletes files.
- The GOAP engine automatically chains multi-step plans from high-level goals.
- Performance predictions improve on subsequent runs via gradient descent learning.
- The relational performance database is populated with correct SQL records.
- Synthesized functions (from the self-healing engine) pass their contract checks.
Each spec is run through a preprocessor (run_*_preproc.patlang) that expands includes and writes
an expanded file, then compiled and executed with patc1.exe. The BDD runner reports pass/fail
per scenario.
The self-healing engine
The most experimental part of Friendly CLI is lib/self_healing_engine.patlang. When a required
host function is missing, the engine can:
- Query a local Ollama model for the Windows command to accomplish the task.
- Synthesize a PatLang wrapper function with Design-by-Contract preconditions and postconditions.
- Generate a BDD specification for the synthesized function.
- Write both files to disk and compile them with
patc1.exe. - Run the BDD spec to verify the function works before registering it as a new action.
This is the full circle of the self-hosting philosophy: not only is the compiler written in PatLang, but the tools that extend the language's capabilities are also written in PatLang, verified by PatLang, and compiled by PatLang.
Dynamic tool discovery
lib/tool_discovery.patlang scans the system PATH for available native tools (Pandoc,
PowerShell, etc.) and generates PatLang source code that registers them as GOAP actions with DbC contracts.
The generated catalog is written to discovered_catalog.patlang and only rewritten when the set of
available tools changes — an incremental check that avoids unnecessary file writes.
Running Friendly CLI
The main demo driver is run_demo.patlang. It dynamically loads the regex DSL, syntax DSL, action
library, and file operations pack, then constructs and runs a driver script that:
- Loads the syntax pack definitions.
- Reads a novice script (the
do_files { ... }block). - Expands the natural-language DSL into PatLang statements.
- Tokenizes, parses, lowers, and executes the expanded program via
run_ir.
pat --ir-run friendly_cli/run_demo.patlang
The BDD verification suites are run similarly, each with its own preprocessor:
pat --ir-run friendly_cli/run_smart_preproc.patlang
pat --ir-run friendly_cli/run_bdd.patlang
Key design insights
The string-bool convention
Throughout Friendly CLI, file existence is checked with file_exists(path) == "1", not
== true. This is PatLang's documented "legacy string-bool convention" — file_exists
returns the string "1" or "0", not a boolean. The action library handles both forms
with (file_exists(path) == "1") or (file_exists(path) == true) for robustness.
Contracts before execution
Every action that touches the filesystem or shells out to a native tool wraps its work in
require/ensure contracts. A failed precondition aborts before any work is done;
a failed postcondition aborts after, reporting exactly what went wrong. This is not defensive programming
– it is correctness by construction, the same principle that governs the rest of the PatLang
ecosystem.
Learning from real data
The performance model starts with a rough guess (35 ms/line, 5000 ms startup) and improves with every execution. The gradient descent learning rate is tiny for line-count-based tasks (to avoid overflow from large line numbers) but larger for file-count-based tasks like zipping. The model persists to disk between runs, so the system gets faster and more accurate the more it is used.
Where it lives in the PatLang ecosystem
Friendly CLI sits at the intersection of several PatLang capabilities:
- Self-hosted dev tools — the same philosophy of building tools in PatLang, for PatLang.
- BDD framework — all Friendly CLI features are verified by Gherkin specs.
- Design by Contract — every action is wrapped in preconditions and postconditions.
- Goal-oriented programming — the GOAP engine is the same paradigm applied to task planning.
- Dynamic syntax — the DSL syntax packs use the same
syntaxblock mechanism.