How the example runner scans JavaScript files, turns them into Glazed verbs, and executes them.
This page explains what jsverbs-example does and how to use it to validate JavaScript-backed commands quickly.
The example runner itself still scans from a directory passed through --dir, but the underlying pkg/jsverbs package is now broader than that one CLI shape. The library can scan a real directory, a generic fs.FS such as an embed.FS, or raw in-memory source strings. The runner is therefore best thought of as the simplest interactive harness for the package, not as the complete boundary of what jsverbs supports.
The runner walks a directory recursively and inspects .js and .cjs files. It extracts:
__package__, __section__, and __verb__ metadata,doc\...`` prose blocks for long help.Under the hood, the scanner now parses metadata literals directly from the tree-sitter AST instead of rewriting JavaScript object text into JSON. That means metadata support is intentionally strict: literal objects, arrays, strings, numbers, booleans, and null are supported, while dynamic expressions inside metadata are rejected. This is a deliberate design choice so command discovery stays deterministic and scanner failures are easier to explain.
By default, public top-level functions become commands even without explicit __verb__ metadata. Files under subdirectories become nested command groups.
Library callers and generated xgoja binaries can narrow directory/fs.FS scans with include/exclude filters. The filters match slash-separated paths relative to the scan root and are intended for application layouts that contain both authored verb files and generated JavaScript assets. For example, an xgoja app can scan path: . but include only site.js and exclude assets/** or dist/**.
Each discovered function is compiled into an ordinary Glazed command. Scalar parameters become Glazed fields, file-local sections become flag groups, and the JavaScript result is converted back into rows:
value column,Promise: awaited before conversion.Some verbs can opt out of structured output entirely. When a verb declares output: "text", the runner exposes it as a writer-style command and prints the returned string directly instead of building a table.
The section story now has one extra layer that matters if you are embedding pkg/jsverbs in Go code instead of only using the example runner. __section__ still declares sections local to one JavaScript file. A Go caller can additionally register registry-level shared sections with Registry.AddSharedSection(...) or Registry.AddSharedSections(...). When both exist for the same slug, the file-local section wins.
Positional arguments are treated as required unless a default value is declared. That means jsverbs-example basics echo now fails with usage instead of silently producing no rows.
The package also has a stricter error model now. Invalid metadata is recorded as scan diagnostics and, by default, scan functions fail with a ScanError instead of silently dropping the broken section or verb. That change matters because it turns missing-command debugging from guesswork into a direct scanner error.
List what was discovered first:
jsverbs-example --dir ./examples/jsverbs/basic list
Run a simple command:
jsverbs-example --dir ./examples/jsverbs/basic basics greet Manuel --excited
Run a verb that writes plain text instead of structured rows:
jsverbs-example --dir ./examples/jsverbs/basic basics banner Manuel
Run a command that uses a shared section:
jsverbs-example --dir ./examples/jsverbs/basic basics list-issues go-go-golems/go-go-goja --state closed --labels bug --labels docs
Run the dedicated example that uses a host-registered shared section instead of a file-local __section__:
jsverbs-example --dir ./examples/jsverbs/registry-shared issues list-issues go-go-golems/go-go-goja --state closed --labels bug --labels docs
If you are working inside Go rather than through the example binary, the package-level entrypoints are now:
jsverbs.ScanDir(...)
jsverbs.ScanFS(...)
jsverbs.ScanSource(...)
jsverbs.ScanSources(...)
That is worth remembering because the example runner is intentionally simpler than the package API. A future application can embed command files at build time or synthesize them in memory without first writing them to disk.
The example runner exposes standard Glazed logging flags on the root command. The default log level is error so module-registration debug logs stay out of the way during normal use. Raise the level explicitly when debugging loader behavior:
jsverbs-example --log-level debug --dir ./examples/jsverbs/basic list
| Problem | Cause | Solution |
|---|---|---|
| A command prints nothing | A required positional argument was omitted earlier and the function returned undefined | Re-run with the required positional argument or inspect --help |
Relative require() fails | The helper file is outside the scanned directory or uses an unsupported resolution path | Keep helper files under the scanned tree and use relative imports like ./helper |
| A function is not listed | It is not top-level, starts with _, is only defined as an object method, metadata parsing failed, or scan filters excluded the file | Export it as a top-level function, check scanner errors, and verify include/exclude filters |
A __verb__ block seems to be ignored | The metadata used dynamic JavaScript instead of static literals | Restrict metadata to literal objects, arrays, strings, numbers, booleans, and null |
The fswatch fixture says fswatch is not defined | The default jsverbs-example runtime does not install host-specific connected helpers | Run the integration test or embed pkg/jsverbs with a runtime that installs jsevents.Install() and jsevents.FSWatchHelper(...); see connected-eventemitters-developer-guide. |
glaze help jsverbs-example-fixture-formatglaze help jsverbs-example-developer-guideglaze help jsverbs-example-referenceglaze help connected-eventemitters-developer-guide