comby-js is a JavaScript build of Comby's core structural match and rewrite
engine. It is intended for embedding Comby-style matching in Node or browser
tooling without shelling out to the native comby binary.
This package uses the simplified Omega-only kernel from comby. Regex
holes default to JavaScript RegExp in the generated JS bundle, with OCaml Re
available as a fallback.
Install OCaml dependencies in an OCaml 5 switch:
opam switch create comby-ocaml-5 ocaml-base-compiler.5.3.0
opam install --switch=comby-ocaml-5 . --deps-onlyBuild the JavaScript bundle and copy it to dist/:
makeThis runs Dune under the active opam switch and writes:
dist/comby.js
To build with a specific switch:
OPAMSWITCH=my-switch makeClean generated Dune and JavaScript package artifacts:
make cleanInstall the local command, if you want comby on your PATH:
npm install -g .You can also run it directly from the checkout:
printf 'foo(1); foo(2);' \
| node bin/comby.js 'foo(:[x])' 'bar(:[x])' .js -stdin -stdoutRun the smoke tests:
make testRun a synthetic benchmark:
node bench/large.js 10000comby accepts a small Comby-compatible command shape:
comby MATCH_TEMPLATE REWRITE_TEMPLATE [EXTENSION] [FILES...] [OPTIONS]Run directly from the checkout:
printf 'foo(1); foo(2);' \
| node bin/comby.js 'foo(:[x])' 'bar(:[x])' .js -stdin -stdoutAfter npm install -g ., invoke the installed binary:
printf 'foo(1); foo(2);' \
| comby 'foo(:[x])' 'bar(:[x])' .js -stdin -stdoutPrint matches as JSON lines:
printf 'foo(1); foo(2);' \
| comby 'foo(:[x])' '' .js -stdin -match-only -json-linesRewrite a file in place:
comby 'foo(:[x])' 'bar(:[x])' .js src/file.js -in-placeUseful options:
-stdin: read source from stdin-stdout: print rewritten source to stdout-match-only,-only-matching,-o: print matches instead of rewriting-json-lines: print one JSON object per input-count: print match counts-in-place: rewrite file inputs in place-matcher,-lang,-l: set the matcher extension, for example.js-rule RULE: apply a Comby rule-regex-backend js|re: select JavaScriptRegExpor OCamlReregex holes
The CLI currently implements the basic match/rewrite path. It does not include the full native Comby command surface for project-wide search, interactive review, diff display, or editor integrations.
const comby = require("comby-js");
const source = "foo(1); foo(2);";
const matches = JSON.parse(
comby.match(source, "foo(:[x])", ".js", "")
);
console.log(matches.length); // 2
const rewritten = comby.rewrite(
source,
"foo(:[x])",
"bar(:[x])",
".js",
""
);
console.log(rewritten); // "bar(1); bar(2);"The third argument is a language extension or matcher selector, for example
.js, .go, .py, or .generic. The fourth argument is an optional Comby rule
string. Pass "" when no rule is needed.
Returns a JSON string containing matches.
const json = comby.match("foo(1)", "foo(:[x])", ".js", "");
const matches = JSON.parse(json);Each match includes:
range: start/end offsets and line/column positionsenvironment: captured metavariablesmatched: the matched source text
Returns the rewritten source string.
comby.rewrite("foo(1)", "foo(:[x])", "bar(:[x])", ".js", "");
// "bar(1)"If there are no matches, the original source is returned.
Returns a JSON string with a rewritten_source field.
JSON.parse(comby.rewriteJson("foo(1)", "foo(:[x])", "bar(:[x])", ".js", ""));
// { rewritten_source: "bar(1)" }Substitutes a rewrite template using a JSON-encoded Comby environment.
This is useful when you already have a match environment from match().
const [first] = JSON.parse(comby.match("foo(1)", "foo(:[x])", ".js", ""));
comby.substitute("bar(:[x])", JSON.stringify(first.environment));
// "bar(1)"Selects the regex backend for regex holes.
comby.setRegexBackend("js"); // default in the JS bundle
comby.setRegexBackend("re"); // OCaml Re fallbackReturns the active backend name.
Returns the active regex backend:
comby.getRegexBackend(); // "js" or "re"Regex holes use Comby's :[name~regex] syntax:
const matches = JSON.parse(
comby.match("abc123 def456", ":[x~[a-z]+]:[n~[0-9]+]", ".txt", "")
);With the default JS backend this uses JavaScript RegExp syntax. Use
JavaScript-style regex patterns such as [A-Za-z].
- The generated bundle is CommonJS.
- Implementation details for future maintainers and coding agents are in
AGENTS.md.