Skip to content

CLI Commands

  • frankiec - launch the REPL
  • frankiec new <project> - scaffold a new project
  • frankiec run <file.fk> - run a program
  • frankiec build <file.fk> - compile to Python source
  • frankiec bundle <file.fk> [-o out.py] - compile to ONE self-contained .py (v1.18)
  • frankiec check [--strict] <file.fk | dir> - syntax check + static analysis (v1.17); directories recurse (v1.18)
  • frankiec test [file.fk] [--filter <name>] [--tag <tag>] - run test suite (default: test.fk)
  • frankiec fmt [--write] [--check] <file.fk | dir> - auto-format; directories recurse (v1.18)
  • frankiec docs [--output out.md] <file.fk> - generate docs
  • frankiec lsp - start the Language Server (v1.18)
  • frankiec stitch install <name> [--global] - install a stitch from the registry (v1.17)
  • frankiec stitch list - list installed + registry stitches (v1.17)
  • frankiec stitch verify - check installed stitches against stitch.lock (v1.18)
  • frankiec stitch update [name] - re-fetch + re-pin stitches (v1.18)
  • frankiec repl [--no-banner] - interactive REPL
  • frankiec watch <file.fk> [--test] - re-run on save
  • frankiec version - show version
  • frankiec --help - full usage
  • frankiec <cmd> --help - per-command help

frankiec lsp — Language Server (v1.18)

Frankie speaks the Language Server Protocol over stdio, built directly on the static analyzer:

  • Live diagnostics — undefined names, wrong argument counts, unused variables, lex/parse errors — as you type.
  • Completion — stdlib functions (with signatures + docs), your own functions, records, enums, and keywords.
  • Hover — signatures and documentation; ## doc-comments above your defs show up in hover cards.

The VS Code extension in the compiler repo (editors/vscode/) launches the server automatically. For Neovim (0.10+):

vim.filetype.add({ extension = { fk = "frankie" } })
vim.api.nvim_create_autocmd("FileType", {
  pattern = "frankie",
  callback = function()
    vim.lsp.start({ name = "frankie", cmd = { "frankiec", "lsp" } })
  end,
})

For Helix (languages.toml):

[language-server.frankie]
command = "frankiec"
args = ["lsp"]

[[language]]
name = "frankie"
scope = "source.frankie"
file-types = ["fk"]
language-servers = ["frankie"]

frankiec bundle — One-File Distribution (v1.18)

frankiec bundle app.fk -o app.py
python3 app.py        # anywhere Python 3.8+ exists — no Frankie needed

The bundle inlines the entire Frankie stdlib and pre-compiles every statically referenced filerequire, import and stitch targets, recursively. At runtime they resolve from an embedded registry instead of the filesystem. Dynamic paths (computed at runtime) can't be bundled and produce a warning.

Write a tool, hand someone a single file. That's the whole story.


frankiec check — Static Analysis (v1.17)

check used to be syntax-only. It now finds real bugs before the program runs:

$ frankiec check app.fk
  ✗  app.fk:11 — Undefined function: 'greeet'
  ✗  app.fk:9  — greet() expects 1..2 argument(s), got 3
  ⚠  app.fk:3  — Unused variable 'unused_thing' in function 'greet'

[Frankie] app.fk — 2 error(s), 1 warning(s)
  • Undefined variables/functions and wrong argument counts are errors (exit 1); unused locals are warnings.
  • require, stitch and import targets are resolved and analyzed, so multi-file programs check cleanly.
  • Names inside string interpolation ("#{typo}") are checked too.
  • --strict makes warnings fail the build (CI mode).
  • If a required file can't be resolved (dynamic path), undefined-name errors downgrade to warnings instead of guessing.
  • Since v1.18, check and fmt accept directories and recurse into .fk files:
frankiec check .              # analyze the whole project
frankiec check --strict src   # CI mode — warnings fail too
frankiec fmt --check .        # formatting gate
frankiec fmt --write .        # fix everything in place

frankiec test — Filtering (v1.17)

frankiec test                    # run everything
frankiec test --filter math      # only test groups whose name contains "math"
frankiec test --tag slow         # only test groups tagged "slow"

Works with test "name", tags: [...] do ... end groups — skipped groups are reported in the summary. See the Testing page.


frankiec stitch — Stitch Installer (v1.17)

frankiec stitch install frankiecolor            # → ./stitches/
frankiec stitch install frankiecache --global   # → ~/.frankie/stitches/
frankiec stitch list                            # installed + registry
frankiec stitch verify                          # v1.18 — ✓ pinned · ⚠ modified · ✗ missing
frankiec stitch update [name]                   # v1.18 — re-fetch + re-pin

Stitches are fetched straight from the Frankie GitHub repository using the Python stdlib HTTP client — a package manager with no packaging.

Since v1.18, installs are pinned in stitch.lock (sha256, source, size, date). Commit the lockfile for reproducible builds; verify exits 1 on problems, so it drops straight into CI. Global installs (--global) don't touch the lockfile.


REPL (v1.17 upgrades)

fk> 2 + 3
=> 5
fk> _ * 10
=> 50
fk> help parallel_map
  parallel_map(vec, fn, workers=4)
    parallel_map(vec, workers: 4) do |x| ... end
    Runs the block across a thread pool...
  • Bare expressions echo their value (=>), like Ruby's irb.
  • _ always holds the last echoed result.
  • help <function> shows the signature and documentation of any stdlib or user-defined function.