leftium
v0.4.3
Published
A project convention CLI for creating projects and applying add-ons.
Maintainers
Readme
Leftium
Leftium creates projects and applies project conventions through add-ons. The implemented built-ins are le add license, le add gitattributes, and le add pages. Other add-ons in Svelte projects delegate to the bundled sv CLI. A narrow Svelte creation implementation is published experimentally and serves as the creation architecture spike. Broader supported creation UX and environment coverage remain in progress; see the active spec.
Install the published CLI with Node 24:
pnpm add -g leftium
le --version
le --help
le create my-app --no-install
le add license
le add gitattributes --preset nodiffleftium and le are aliases for the same executable. Use le add license in the directory you want to license, or pass -C /path/to/project.
The selected directory can be empty and needs neither Git nor package.json. An equivalent license is preserved, including an alternate filename. Different or customized content requires interactive confirmation or --force; inconsistent multiple license files must be resolved manually. If the selected directory has a package.json, only its license field is updated. Ancestor package manifests are not edited.
Useful options:
le add license -C ./project --non-interactive --author "Your Name"
le add license -C ./project --force --author "Your Name" --year 2020-2026
le add license -C ./packages/app --package-license --author "Your Name"Explicit author and year values win. Otherwise, an existing canonical MIT notice supplies them; author inference then tries the target package author and Git's configured name. A new notice defaults to the current year. Missing author input prompts in a terminal and fails in automation. --package-license explicitly permits a separate license in a workspace package when an ancestor license exists; --force alone does not make that scope choice. This slice recognizes npm/Yarn workspace globs and explicit pnpm workspace package lists.
--no-install is accepted; the license operation needs no package installation. Completed applied/no-op requests exit zero. Conflicts, unsupported requests, cancellation, and failures exit nonzero. Failures can leave partial output; the report names affected files. Leftium does not stage or commit changes.
Svelte add-ons
In a Svelte or SvelteKit package, unknown add-on names run through the pinned sv dependency. Built-in names always select Leftium; prefix a name with sv: to select upstream behavior explicitly.
le add prettier --no-install --no-git-check
le add sv:prettier -C ./packages/app --no-install
le add @example/sv --no-install
le add file:../my-addon=who:hello --no-install --no-download-checkSupply the add-on before upstream options. Leftium consumes -C / --cwd and passes the nearest enclosing package root to sv; a workspace root does not select a child app. Other arguments, including inline add-on options and additional upstream add-ons, reach sv unchanged. Relative file: requests are resolved by sv against that package root.
Upstream owns prompts, dependency installation, output, and exit status. Use explicit add-on options and upstream flags such as --no-install, --no-git-check, and --no-download-check for automation. Leftium's --non-interactive applies to built-ins and is rejected on delegation. Non-Svelte packages fail before launching sv. Leftium reports delegation without claiming to verify upstream changes.
GitHub Pages
For a standalone, fully prerendered SvelteKit app, le add pages configures static output and creates a caller pinned to the reusable Leftium workflow. Adapter-auto replacement requires an explicit choice.
le add pages --repository owner/repository --replace-adapter --node-version 24
le add pages --repository owner/repository --replace-adapter --node-version 24 --no-installDeclare the package manager in package.json or pass --package-manager; pnpm also needs an exact version. Use --site-url https://example.com/ for a custom domain. Leftium verifies local static routes/assets when it runs the build and reports skipped verification with --no-install. GitHub Pages settings, DNS, and deployed-site verification remain explicit follow-up. Workspace deployment and SPA fallbacks are unsupported. See the Pages adoption and maintenance guide for the workflow contract, updates, supported customization, and troubleshooting.
Development
Use Node 24 and pnpm 12.3.4:
pnpm install --frozen-lockfile
pnpm build
pnpm start add license -C /path/to/project --author "Your Name" --year 2026pnpm test # compile both languages, then run Node fixture and unit tests
pnpm typecheck # generate the ReScript boundary and check TypeScriptAfter an initial build, use two terminals for incremental compilation:
pnpm dev:rescript
pnpm dev:typescriptPublishing
Publishing is driven by a package.json version change pushed to main.
Choose and create the version locally, then push the version commit:
pnpm version patch # or minor, prerelease, or another explicit version
git pushBefore the first automated release, configure leftium's Trusted Publisher in
npm package settings: GitHub Actions, owner Leftium, repository le, and
workflow filename publish.yml. Allow direct npm publish. This workflow uses
GitHub Actions OIDC, so no npm token or Git tag push is required.
TypeScript owns discovery, template loading and rendering, prompts, file edits, and reporting. License.res owns license-state classification and reconciliation decisions for the MIT, Apache-2.0, BSD-3-Clause, and ISC presets. runAdd accepts ordinary requests without Commander, so tests and the CLI share orchestration.
ReScript's genType integration generates the typed import used by TypeScript. Generated .res.js, .gen.tsx, and dist/ files are ignored and rebuilt locally. Edit the .res source instead of those generated files. The build uses the ReScript compiler and tsc directly, without a bundler.
The first boundary needs no handwritten representation adapter: TypeScript narrows the generated decision union by its TAG. Pure tests exercise it without filesystem setup, and TypeScript source maps support shell debugging. ReScript calculations can currently be inspected in their readable generated JavaScript; source-level ReScript debugging has not been established. The richer creation request/recipe model remains the second test of whether this split is useful before extracting a shared add-on API.
