Stitches
What are stitches?
Frankie's zero-dependency, zero-registry package system. Drop a .fk file in the right folder and stitch it in.
| Feature | Category | Summary |
|---|---|---|
stitch "name" |
language | Load a package by name — resolves from ./stitches/ then ~/.frankie/stitches/ |
frankieforms |
stitch | Form field validation — required, min/max length, email, numeric, pattern |
frankietable |
stitch | ASCII table rendering from a vector of hashes |
frankiecolor |
stitch | ANSI color helpers for terminal output |
frankiepager |
stitch | Pagination math — total pages, slicing, prev/next |
frankieconfig |
stitch | Layered config loading from defaults, JSON file, and env vars |
frankiestring |
stitch | Additional string functions |
frankietemplate |
stitch | Mustache-compatible template rendering for Frankie |
frankiecookie |
stitch | Signed cookie helpers for Frankie |
frankieauth |
stitch | HTTP Basic Auth and Bearer token authentication — introduced in v1.15 |
frankieratelimit |
stitch | In-memory per-IP sliding-window rate limiting — introduced in v1.15 |
frankiemail |
stitch | Send email via SMTP — plain text or HTML, CC/BCC — introduced in v1.16 |
frankiecli |
stitch | Structured CLI argument parsing — flags, options, subcommands — introduced in v1.16 |
frankiecache |
stitch | In-memory key/value cache with optional TTL — introduced in v1.16 |
| --- |
The stitch Keyword
stitch loads a Frankie package by name. It resolves the file in two locations, in order:
./stitches/<name>.fk— project-local (checked first)~/.frankie/stitches/<name>.fk— user-global
If neither exists, a clear error tells you exactly what to do:
╔══ Frankie Runtime Error ══════════════════════════════
║ [Frankie] Stitch not found: "frankieforms"
║ Put frankieforms.fk in ./stitches/ or ~/.frankie/stitches/
╚═══════════════════════════════════════════════════════
Each stitch is loaded at most once — calling stitch "name" multiple times in the same program is safe.
Installing Stitches (v1.17)
The stitch installer fetches stitches straight from the Frankie GitHub repository using the Python stdlib HTTP client — a package manager with no packaging:
frankiec stitch install frankiecolor # → ./stitches/
frankiec stitch install frankiecache --global # → ~/.frankie/stitches/
frankiec stitch list # installed + registry
Lockfile — stitch.lock (v1.18)
Installing a stitch pins it in stitch.lock (sha256, source, size, date). Commit the lockfile and your builds are reproducible:
frankiec stitch install frankiecolor # writes/updates stitch.lock
frankiec stitch verify # ✓ pinned · ⚠ modified · ✗ missing
frankiec stitch update # re-fetch everything + re-pin
frankiec stitch update frankiecolor # or just one
verify exits 1 on problems — drop it straight into CI. Global installs (--global) don't touch the lockfile.
Compared to require
require |
stitch |
|
|---|---|---|
| Path | Explicit: require "lib/utils" |
By name: stitch "frankieforms" |
| Resolution | Relative to cwd | ./stitches/ then ~/.frankie/stitches/ |
| Signals | Your own code | Third-party packages |
| Convention | lib/ folder |
stitches/ folder |
They use the same underlying machinery — stitch is require with a conventional resolution path and a more meaningful name for the job.
Project layout with stitches
myapp/
├── main.fk
├── test.fk
├── lib/
│ └── utils.fk ← your own code, loaded with require
└── stitches/
├── frankieforms.fk ← third-party, loaded with stitch
└── frankietable.fk
Anyone cloning your repo immediately knows what stitches/ contains.
Writing Your Own Stitch
A stitch is any .fk file. Drop it in ./stitches/ and stitch "name" loads it.
# stitches/myutils.fk
def slugify(s)
s.downcase.gsub("[^a-z0-9]+", "-").strip
end
def truncate(s, n)
if s.length <= n
s
else
s[0...n] + "..."
end
end
# main.fk
stitch "myutils"
puts slugify("Hello World!") # hello-world
puts truncate("Long string", 4) # Long...
Conventions
- Prefix private helper functions with
_to signal they're internal. - Use
##doc-comments forfrankiec docscompatibility. - Keep each stitch focused on one concern.
- Avoid redefining stdlib functions.