Advanced Features#
Multi-File Templates#
A single template can generate multiple files at once. Ideal for patterns like:
- Screen + ViewModel + Test
- Controller + Service + DTO
- Entity + Repository + Migration
Setup in configs.yaml#
templates:
- name: screen
description: Flutter screen with ViewModel
files:
- path: screen/view.lokio
output: lib/features/<%= snakeCase(name) %>/view/<%= snakeCase(name) %>_screen.dart
- path: screen/viewmodel.lokio
output: lib/features/<%= snakeCase(name) %>/viewmodel/<%= snakeCase(name) %>_viewmodel.dart
- path: screen/test.lokio
output: test/features/<%= snakeCase(name) %>/<%= snakeCase(name) %>_test.dart
parameters:
- name: name
type: string
required: true
prompt: "Screen name:"Generate#
lokio g screen LoginOutput:
Generating 3 files...
✓ Generated: lib/features/login/view/login_screen.dart
✓ Generated: lib/features/login/viewmodel/login_viewmodel.dart
✓ Generated: test/features/login/login_test.dart
Code generation complete! (3 files)
Hooks (Post-Generation)#
Run commands automatically after lokio gen succeeds. Define them in lokio/configs.yaml:
templates:
- name: service
description: NestJS service
path: service.lokio
output: src/services/<%= pascalCase(name) %>Service.ts
parameters:
- name: name
type: string
required: true
prompt: "Service name:"
hooks:
after_gen:
- bun run format # format code after generation
- bun run build:check # ensure no TypeScript errorsOutput during generate:
✓ Generated: src/services/UserService.ts
Running post-generation hooks...
✓ bun run format
✓ bun run build:check
Code generation complete! (1 file)
More Hook Examples#
hooks:
after_gen:
- go mod tidy # Go: update dependencies
- flutter pub get # Flutter: install packages
- npx prettier --write src/ # format with Prettier
- php artisan optimize # Laravel: clear cacheNote: Hooks run from the project root folder. If a hook fails, generation is still considered successful — only a warning is shown.
Sync & 3-Way Merge#
The Problem It Solves#
You already generated UserService.ts from a template. Then:
- You manually added a
getUserById()method to the file - The
service.lokiotemplate was updated by your team (e.g. the constructor changed)
If you directly overwrite, the method you added is lost. Lokio solves this with 3-way merge.
How 3-Way Merge Works#
base = the file version stored in git (git show HEAD:<file>)
current = the current file (possibly modified by you)
theirs = the re-rendered result from the updated template
Rules:
- Only you changed it → your changes are preserved
- Only the template changed → template changes are applied
- Both changed the same lines → conflict markers are written
Preview with lokio diff#
Before applying, see what will change:
lokio diff ✓ src/services/AuthService.ts — up to date
~ src/services/UserService.ts — +2 -1 (your edits preserved)
✗ src/services/OrderService.ts — conflict (resolve markers manually)
1 conflict detected.
2 files can be updated — run lokio sync to apply
Run Sync#
lokio syncScanning 3 generated files...
✓ src/services/AuthService.ts — up to date
~ src/services/UserService.ts — +2 -1 (your edits preserved)
✗ src/services/OrderService.ts — conflict (resolve markers manually)
1 conflict detected — conflict markers will be written.
2 files can be updated.
? How do you want to proceed?
› Apply all changes
Review each file
Cancel
Resolving Conflicts#
Conflict files will contain markers:
export class OrderService {
// New method from template
async voidOrder(id: number) {
return this.repo.void(id);
}
}Edit the file, pick or merge the parts you want, then remove the <<<<<<<, =======, >>>>>>> markers.
Requirements for 3-Way Merge#
The file must have already been committed to git. If not, Lokio will ask for confirmation before overwriting.
lokio check — Structural Lint#
Validate whether files in the repo follow the structural rules defined in your templates.
Difference from
lokio sync:synconly cares about files tracked inlokio.lock.checkcan detect any file in the repo whose path matches a template's output pattern — including files written manually without Lokio.
How It Works#
Lokio reads annotations from .lokio files and automatically creates lint rules.
Auto-Fingerprinting#
Every line containing <%= %> is automatically turned into a required + danger rule:
// lokio/templates/service.lokio
import { Injectable } from '@nestjs/common'; // ← this line becomes a required rule
@Injectable() // ← this one too
export class <%= pascalCase(name) %>Service {}Meaning: all files matching this template's output pattern must contain import { Injectable } and @Injectable().
Manual Annotations#
More explicit and flexible:
<%# @lokio required danger "Must have @Injectable()" @Injectable %>
<%# @lokio forbidden warning "Do not use console.log" console\.log %>
<%# @lokio required warning "Must export class" export class %>
@Injectable()
export class <%= pascalCase(name) %>Service {}Annotation format:
<%# @lokio <required|forbidden> <danger|warning> "message" [regex-pattern] %>
| Part | Value | Description |
|---|---|---|
required | — | File must contain this pattern |
forbidden | — | File must not contain this pattern |
danger | — | Reported as an error |
warning | — | Reported as a warning |
"message" | text | Message shown to user |
[pattern] | regex | Optional; if absent, the next line is used as the pattern |
Configuration in lokio/configs.yaml#
check:
danger_mode: block # "block" = exit code 1 (fits pre-commit hook)
# "warn" = display only, no exit 1
# templates: # optional — omit to check all templates
# - service
# - controllerUse as a Pre-commit Hook#
# .git/hooks/pre-commit
#!/bin/sh
lokio checkOr with Husky / Lefthook:
# .lefthook.yml
pre-commit:
commands:
lokio-check:
run: lokio checklokio ai — AI Standards Validation#
Use AI to validate team standards that can't be caught by regex — such as the presence of test files, documentation, or architectural patterns.
Setup#
1. Configure in lokio/configs.yaml (safe to commit):
ai:
provider: gemini # openai | anthropic | gemini | ollama | openrouter
model: gemini-2.0-flash
standards:
- id: unit-test
description: "Every service must have a unit test file"
severity: danger
- id: no-console-log
description: "No console.log in production code"
severity: warning
- id: has-readme
description: "Every package/module must have a README"
severity: warning2. API key in lokio.local.yaml (gitignored — do not commit):
# lokio.local.yaml
ai:
api_key: YOUR_API_KEY_HEREOr environment variable:
export LOKIO_AI_API_KEY=your-keyRun#
lokio aiIf not yet configured, an interactive wizard will guide you through setup and create lokio.local.yaml automatically.
Supported Providers#
| Provider | Recommended model | Notes |
|---|---|---|
gemini | gemini-2.0-flash | Free tier, recommended to start |
openai | gpt-4o-mini | Affordable |
anthropic | claude-haiku-4-5-20251001 | — |
openrouter | meta-llama/llama-3.3-70b-instruct:free | Free models available |
ollama | llama3.2 | Local / VPS, no API key needed |
Ollama configuration:
ai:
provider: ollama
model: llama3.2
endpoint: http://your-vps:11434 # default: http://localhost:11434Severity#
danger— if it fails, the command exits with code 1 (fits CI/CD gate)warning— displayed only, does not block
lokio doctor — Setup Diagnostics#
Check your entire Lokio setup in one command:
lokio doctorUseful for:
- Onboarding new developers to the team
- Debugging when a command isn't working
- Verifying API keys and AI configuration before running
lokio ai
lokio.lock — Generation Tracking#
The lokio.lock file is automatically created and updated every time lokio gen succeeds.
# lokio.lock
generations:
- template: service
parameters:
name: UserService
files:
- output: src/services/UserService.ts
template_path: service.lokio
generated_at: "2026-03-09T10:00:00.000Z"Rules:
- ✅ Commit to git — so the whole team can use
lokio syncandlokio diff - ❌ Don't edit manually unless you know what you're doing
Why is it safe to commit?
- Small file — only stores template name, parameters, and output path
- Does not store file contents (for merge base, Lokio uses
git show HEAD) - Conflicts in
lokio.lockare easy to resolve (simple YAML format)
Automatic deduplication: If the same file is re-generated from a different template, Lokio automatically transfers file ownership to the latest template — no duplication in the lock file.
AI Key Security#
| File | Commit? | Contents |
|---|---|---|
lokio.yaml | ✅ Yes | Project metadata, enterprise config |
lokio/configs.yaml | ✅ Yes | Templates, check config, AI provider & model |
lokio.local.yaml | ❌ No | API key (auto-gitignored during lokio init) |
lokio.lock | ✅ Yes | Generation tracking |
lokio.local.yaml is automatically added to .gitignore during lokio init. If this file is absent, Lokio also accepts the API key from the LOKIO_AI_API_KEY environment variable.
Enterprise Hub#
For teams that want to share templates across projects:
# Activate during init
lokio init --enterprise ENT-xxxxxx
# Or use the flag directly
lokio init -e ENT-xxxxxx
# Pull templates from the hub
lokio pullAfter lokio init --enterprise, run lokio pull to populate templates from the Hub into lokio/configs.yaml and lokio/templates/.