@forgerock/login-framework-cli
v0.1.0
Published
CLI tool for scaffolding and managing Ping Login Widget and Login App custom component projects
Readme
ping-lf — Ping Login Framework CLI
CLI for initializing, scaffolding, and updating Ping Login Widget and Login App custom component projects.
Prerequisites
- Node.js >= 20.0.0
- pnpm >= 9
Installation
npm install -g @forgerock/login-framework-cliOr run directly without installing:
npx @forgerock/login-framework-cli init my-projectCommands
ping-lf init <directory>
Bootstraps a new Login Widget or Login App project into <directory> by fetching the latest framework release from GitHub, copying it with safe exclusions, and setting up the custom component scaffolding.
ping-lf init my-login-project
cd my-login-project
pnpm install
cp .env.example .env # fill in your ForgeRock AM details
pnpm devOptions
| Flag | Description |
| ---------------- | ---------------------------------------------------------------------------------------------------------------------- |
| --tag <tag> | Download a specific release tag (e.g. v1.2.0). Defaults to latest. |
| --local <path> | Use a local framework directory instead of downloading from GitHub. Useful for development or air-gapped environments. |
What it does
- Downloads the framework archive from GitHub Releases (or copies from
--local) - Copies framework files, excluding build artifacts, secrets, and
tools/ - Writes a minimal
pnpm-workspace.yaml - Creates
experimental/custom/callbacks/andexperimental/custom/stages/with.gitkeepplaceholders - Copies the component authoring guide to
experimental/custom/README.md - Writes
.generator-versionto track the framework version in use
The core/journey/_utilities/registry/custom-registry.ts file is generated by the framework's Vite plugin on the first pnpm dev or pnpm build:widget — the CLI never touches it.
ping-lf generate callback <Name>
ping-lf generate stage <Name>
Scaffolds a new custom component under experimental/custom/callbacks/<slug>/ or experimental/custom/stages/<slug>/. The Vite plugin watches these directories during pnpm dev and regenerates custom-registry.ts automatically on add/remove/change.
Run from the root of an initialized project, or pass --directory <path> to target a specific project root.
# Override the built-in NameCallback renderer
ping-lf generate callback NameCallback
# Override the DefaultLogin stage layout
ping-lf generate stage DefaultLogin
# Create a brand-new callback type (paired with a custom AM node)
ping-lf generate callback MyTelemetryCallbackWhat it creates (example for ping-lf generate callback NameCallback):
experimental/custom/callbacks/name-callback/
├── name-callback.svelte # component implementation — edit this
└── name-callback.utilities.ts # helper functions (optional)
└── name-callback.utilities.test.ts # unit test stubThe @component header in the generated .svelte file declares the type and name. The framework's Vite plugin reads this header to register the component:
<!--
@component
Type: callback
Name: NameCallback
-->Setting Name to an existing default (e.g. NameCallback, DefaultLogin) overrides that component. Setting it to a new name extends the framework with a custom type.
See experimental/custom/README.md for the full prop contract.
ping-lf releases
Lists available framework releases from GitHub.
ping-lf releasesping-lf mcp
Boots the CLI as a local MCP server over stdio. Exposes the same commands as typed tools that any MCP-compatible AI assistant can call directly.
Claude Code (project-local)
Create .claude/mcp.json at the root of your login project:
{
"mcpServers": {
"ping-lf": {
"command": "npx",
"args": ["@forgerock/login-framework-cli", "mcp"]
}
}
}Claude Desktop
Add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"ping-lf": {
"command": "npx",
"args": ["@forgerock/login-framework-cli", "mcp"]
}
}
}Available tools
| Tool | Description |
| ------------------- | ------------------------------------ |
| init | Bootstrap a new project |
| generate_callback | Scaffold a custom callback component |
| generate_stage | Scaffold a custom stage component |
| update | Update the framework version |
| list_releases | List available releases from GitHub |
For generate_callback, generate_stage, and update, pass an absolute path via the directory parameter to target a specific project root. If omitted, the server's working directory is used.
ping-lf update
Fetches the latest (or a specified) framework version and overwrites the core framework files while preserving experimental/custom/ and project-level configs. The component registry is regenerated by the Vite plugin on the next build or dev-server start.
Run from the root of an initialized project.
ping-lf update # update to latest
ping-lf update --version v1.5.0 # pin to a specific version
ping-lf update --local ../framework # use a local directory
ping-lf update --directory /path/to/project # target a specific project rootWhat it preserves
experimental/custom/— all custom components are untouchedpnpm-workspace.yaml— your workspace config is not overwritten.envfiles — excluded from the copy
After updating, run pnpm install if the framework's package dependencies changed.
Project layout (after init)
my-login-project/
├── packages/login-widget/ # @forgerock/login-widget
├── apps/login-app/ # SvelteKit dev/docs app
├── core/ # Shared stores, components, journey logic
│ └── journey/_utilities/
│ └── custom-registry.ts # AUTO-GENERATED — do not edit
├── experimental/
│ └── custom/
│ ├── README.md # Component authoring guide
│ ├── callbacks/ # Your custom callback components
│ └── stages/ # Your custom stage components
├── .generator-version # Tracks the framework version in use
└── pnpm-workspace.yamlDevelopment
The CLI is a workspace package inside the framework monorepo, but it is not declared as a dependency of any other workspace. This is intentional: customer-generated projects must not carry a workspace:* link to this CLI, because that protocol only resolves inside this monorepo. The trade-off is that after a fresh clone, ping-lf is not on your $PATH until you set it up.
Recommended setup (once per machine)
From the repo root, after pnpm install:
pnpm --filter @forgerock/login-framework-cli build
pnpm --filter @forgerock/login-framework-cli link --globalpnpm link --global symlinks the CLI's bin (tools/cli/dist/src/main.js) into your machine's global pnpm bin directory, pointing back at this repo's dist/. After this, ping-lf works as a real command from anywhere:
ping-lf init my-project
ping-lf generate callback MyCallback
ping-lf update --tag v1.5.0Rebuilds (pnpm --filter @forgerock/login-framework-cli build) update the global binary automatically — no relink needed.
To remove the global link later: pnpm --filter @forgerock/login-framework-cli unlink --global.
Without the global link
If you'd rather not link globally, invoke the built binary directly. You still need to build first:
pnpm --filter @forgerock/login-framework-cli build
./tools/cli/dist/src/main.js init my-project
# or:
pnpm --filter @forgerock/login-framework-cli exec ping-lf init my-projectOther useful commands
pnpm --filter @forgerock/login-framework-cli test # run unit tests
pnpm --filter @forgerock/login-framework-cli run dev # tsc --watchProject structure
tools/cli/
├── src/
│ ├── main.ts # Entry point — forks to MCP server or CLI
│ ├── mcp.ts # MCP server (ping-lf --mcp)
│ ├── errors.ts # Typed Effect errors
│ ├── commands/
│ │ ├── init.ts # ping-lf init
│ │ ├── generate.ts # ping-lf generate callback|stage
│ │ └── update.ts # ping-lf update
│ ├── services/
│ │ ├── file-system.ts # copyWithExclusions
│ │ ├── release.ts # GitHub release fetch
│ │ └── vite-config.ts # Vite plugin injection
│ └── config/
│ ├── exclusions.ts # Files/dirs excluded from copy operations
│ └── version.ts # .generator-version read/write
├── templates/
│ ├── callback/ # Scaffold templates for callbacks
│ └── stage/ # Scaffold templates for stages
└── test/ # Vitest unit testsTech stack
- Effect — typed async handling, composable services, declarative errors
- @effect/cli — CLI parsing and help generation
- @effect/ai — MCP server (
McpServer,Tool,Toolkit) - @effect/platform-node — Node.js FileSystem, Path, HTTP client
- Vitest — unit tests
