A personal CLI workspace manager (vira) for AI-assisted development workflows. It manages how developer workspaces are populated — by registering reusable Freemarker-templated archetypes and folder sources (catalogs), then generating workspace content from those registrations. Aimed at eliminating manual copy-paste when bootstrapping or updating AI assistant configuration across multiple projects.
Core Value: A developer can register archetypes and catalogs once, then generate a correctly-structured workspace with a single command — and regenerating is safe (skips existing files).
CLI workspace manager for AI-assisted development: register sources (local directories, optionally Freemarker template trees), register destinations (workspace roots), attach mappings from sources into a destination, then generate files or sync non-template files. Generate never overwrites existing files. Sync is local filesystem only (no network, no Git).
Requires JDK 21. Build with ./mvnw package, then java -jar target/viracocha-0.1.jar, or run ./scripts/vira from the repository root (the script builds the fat JAR if missing).
| Concept | Role |
|---|---|
| Central config | Single YAML file (config.yaml) listing sources and destinations. Created by vira config init. Must declare **version: 3**. |
| Source | Named path to a directory. If marked as templates, path segments and file contents are expanded with Freemarker using the destination’s parameters map. |
| Destination | Named workspace root path, optional default parameters (key: value), and a list of mappings. |
| Mapping | Binds a source into that destination: optional glob filter, recurse flag, and **sync: true** to include the mapping in vira sync. |
| Generate | For each mapping, walks the source tree, applies template or binary copy rules, writes under the destination root. Existing destination files are skipped. |
| Sync | For each mapping with sync: true, copies changed non-template source files into the destination using timestamp and content checks; reports conflicts when the destination file is newer than the source and content differs. |
Structured logging (JSONL) is written to ~/.local/share/viracocha/vira.jsonl. Normal command output uses stdout/stderr.
| Item | Location |
|---|---|
| Config file | $XDG_CONFIG_HOME/viracocha/config.yaml when XDG_CONFIG_HOME is set; otherwise ~/.config/viracocha/config.yaml. |
| JSONL log | ~/.local/share/viracocha/vira.jsonl |
If the config file is missing, commands that need it print: Config not initialized. Run 'vira config init' first. If the file exists but **version is less than 3**, load fails with an error that tells you to remove the old file and run vira config init again.
vira config init
vira config showPaths may be absolute or relative; the string must not contain ... The path must exist and be a directory.
vira source add -n my-templates -p /absolute/or/relative/path/to/tree --templates
vira source add -n my-static -p /path/to/static-files
vira source list
vira source show my-templatesShort aliases: -n for --name, -p for --path. --templates marks the source as Freemarker-driven and can record extracted variable names in config. Use vira source remove NAME to unregister.
Destination paths may be absent on disk at registration time (but must not contain .. in the stored string). Tilde (~) in stored paths is expanded when generating or syncing.
vira destination add -n my-app -p /path/to/workspace
vira destination add-mapping my-app --source my-templates --recurse
vira destination add-mapping my-app --source my-static --glob "**/*.md" --sync
vira destination show my-app
vira destination listadd-mapping takes the destination name as the first parameter, then --source (required). Options: --glob, --recurse, --sync (persisted on the mapping; only mappings with sync: true participate in vira sync).
List mappings: vira destination map-ls DEST. Remove one by 0-based index: vira destination remove-mapping DEST 0.
To set Freemarker default parameter values for a destination, edit config.yaml under that destination’s parameters: key. There is no CLI flag for parameters today.
vira generate --dest my-app
vira generate --dest my-app --dry-run
vira generate --dest my-app --verboseIf the destination directory does not exist, you are prompted to create it (y/N), except in --dry-run, which only reports Would create: <path>. Summary line: Generated: …, Skipped: …, Failed: ….
vira sync --dest my-app
vira sync --dest my-app --dry-run
vira sync --dest my-app --verboseOnly mappings with **sync: true** are processed. Template sources are skipped during sync. Human-readable summary: Copied: …, Skipped: …, Failed: …, Conflicts: …. Exit code 1 if there are conflicts or failures. Conflicts occur when a destination file is newer than the corresponding source file and content differs.
Group aliases: vira config → vira cfg, vira source → vira src, vira destination → vira dest, vira generate → vira gen.
| Command | Purpose |
|---|---|
vira config init |
Create config directory and config.yaml if missing. |
vira config show |
Print config file path and raw YAML. |
vira source add |
-n/--name, -p/--path (required); optional --templates. |
vira source list |
Plain name and path columns. |
vira source show NAME |
Multi-line details. |
vira source remove NAME |
Remove a source. |
vira destination add |
-n/--name, -p/--path (required). |
vira destination list |
Plain name and path columns. |
vira destination show NAME |
Multi-line details including mappings. |
vira destination remove NAME |
Remove a destination and its mappings. |
vira destination add-mapping DEST |
--source (required); --glob, --recurse, --sync. |
vira destination map-ls DEST |
Numbered mapping blocks. |
vira destination remove-mapping DEST INDEX |
INDEX is 0-based. |
vira generate |
Required --dest; --dry-run, --verbose. |
vira sync |
Required --dest; --dry-run, --verbose. |
Use vira <group> <subcommand> --help for full option lists.
Use a JDK 21 distribution that includes **native-image** (install tooling for your vendor if needed).
./mvnw -DskipTests -Pgraalvm-native package
./target/vira --helpStack: Java 21, Micronaut 4, Picocli, Freemarker, Jackson YAML, Logback.
References: Micronaut 4 guide, Micronaut Maven plugin.