A Code on the Go plugin (.cgp)
that converts the Android project currently open in the IDE into a Code On The
Go (.cgt) template bundle — driven entirely from a tab inside the IDE, with an
option to install the result straight into the New Project template picker. The
original project directory is never modified: the plugin copies it into a new
bundle directory next to it and templatizes the copy.
This started as a templatize_project.py desktop script, was ported to a
standalone Kotlin/Compose Android app, and is now a Code on the Go plugin so it
runs inside the IDE with no separate app to install.
The plugin adds a Project to Template item to the IDE's sidebar (under "tools"), which opens a tab with:
- Project — read-only, always the project currently open in the IDE
(via
IdeProjectService.getCurrentProject()). If no project is open, conversion is disabled until one is. - Template name — written into the generated
template.json'snamefield, and used as the template subdirectory /templates.jsonpathentry. - Dry run — preview the substitutions against a disposable copy without writing or deleting anything.
- Skip cleanup — skip
build/and keystore removal.
Convert to Template stays disabled until a project is open and a template
name is entered. Tapping it runs the pipeline on a background thread and streams
a live log ([OK] / [SKIP] / [REMOVED] / [REVIEW]), followed by a summary
with the output paths. On a real (non-dry-run) conversion, an Install
Template button then appears below the log — so you can review the log first —
and tapping it registers the .cgt directly with the IDE via
IdeTemplateService, so it shows up immediately in the New Project template
picker.
For each run, it:
- Creates a new output directory (
<project-dir>-cgt, next to the project). - Copies the project into a subdirectory named after the template name,
skipping
.git,.gradle,.cg,.idea,.claude,.androidide, andrelease.properties. - Templatizes the copy: replaces concrete values (Gradle/AGP/Kotlin versions,
package name, app name, SDK levels, Java compatibility levels) with Pebble
tokens (
${{ TOKEN }}), saving each modified file with a.pebsuffix; removesbuild/directories; deletes keystore files (*.jks,*.keystore,*.p12); and flags files that may contain machine-specific or personal information (local.properties,google-services.json,key.properties,GoogleService-Info.plist) for manual review. - Writes a
templates.jsonat the top of the output directory. - Adds a
template/directory containingtemplate.json(the parameter/ metadata schema) and a placeholderthumb.png(replace with a real thumbnail before shipping). - Zips the output directory into a
<template-name>.cgtfile next to it. - If the user opts in, registers that
.cgtwith the IDE viaIdeTemplateService.registerTemplate(...).
Both Kotlin DSL (build.gradle.kts) and Groovy DSL (build.gradle) projects
are supported. Assumes the app module is named app (falls back to the first
module).
A line/segment that ends with a Pebble token must be followed by at least one character of whitespace, or the parser eats the next character (often a newline, quote, semicolon, or dot). The conversion inserts a sacrificial space after every inserted token — after the closing quote when the token is immediately followed by one, so the quote itself isn't eaten.
Templatizer.kt— the substitution pipeline, purejava.io.Filelogic with no dependency on the plugin API (easy to reason about and test in isolation), plus the.cgtbundle writer/zipper.ProjectToTemplatePlugin.kt— theIPluginentry point: registers the sidebar item and the main editor tab, and provides in-IDE tooltip help.fragments/ProjectToTemplateFragment.kt— the tab's UI: the input form, background execution, live log, and the install-template flow viaIdeTemplateService.src/main/assets/docs/index.html— the offline Tier 3 help page.
This plugin uses the shared repo-root ../libs/plugin-api.jar +
../libs/gradle-plugin.jar and the repo-root ../gradlew — it does not bundle
its own copies. See the repo CLAUDE.md for the monorepo conventions.
From this directory, using the repo-root Gradle wrapper:
../gradlew assemblePlugin # release .cgp -> build/plugin/project-to-template.cgp
../gradlew assemblePluginDebug # debug .cgp -> build/plugin/project-to-template-debug.cgp
Install the resulting .cgp through Code on the Go's Plugin Manager. A
local.properties with sdk.dir=<Android SDK path> is required to build.
After running a conversion, inspect the generated .peb files in the output
bundle to confirm the substitutions and spacing look right, and replace the
placeholder thumb.png before distributing the .cgt file.