@maccesar/titools 2.5.0 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +832 -228
  3. package/bin/titools.js +8 -0
  4. package/lib/commands/list.js +105 -0
  5. package/lib/config.js +1 -0
  6. package/package.json +1 -1
  7. package/skills/alloy-guides/SKILL.md +1 -1
  8. package/skills/alloy-howtos/SKILL.md +1 -1
  9. package/skills/purgetss/SKILL.md +1 -1
  10. package/skills/ti-api/SKILL.md +1 -1
  11. package/skills/ti-branding/SKILL.md +225 -0
  12. package/skills/ti-branding/assets/ic_launcher.xml +6 -0
  13. package/skills/ti-branding/references/android-adaptive-icons.md +85 -0
  14. package/skills/ti-branding/references/cleanup-legacy.md +112 -0
  15. package/skills/ti-branding/references/ios-appiconset.md +62 -0
  16. package/skills/ti-branding/references/master-input-guidelines.md +84 -0
  17. package/skills/ti-branding/references/notification-icons.md +63 -0
  18. package/skills/ti-branding/references/splash-screen-api.md +81 -0
  19. package/skills/ti-branding/references/ti-icon-paths.md +84 -0
  20. package/skills/ti-branding/references/tiapp-xml-snippets.md +92 -0
  21. package/skills/ti-branding/scripts/lib/cleanup-legacy.sh +230 -0
  22. package/skills/ti-branding/scripts/lib/deps.sh +58 -0
  23. package/skills/ti-branding/scripts/lib/gen-android-adaptive.sh +52 -0
  24. package/skills/ti-branding/scripts/lib/gen-android-legacy.sh +36 -0
  25. package/skills/ti-branding/scripts/lib/gen-ios.sh +30 -0
  26. package/skills/ti-branding/scripts/lib/gen-marketplace.sh +40 -0
  27. package/skills/ti-branding/scripts/lib/gen-notification.sh +34 -0
  28. package/skills/ti-branding/scripts/lib/gen-splash-icon.sh +31 -0
  29. package/skills/ti-branding/scripts/lib/prepare-master.sh +48 -0
  30. package/skills/ti-branding/scripts/lib/validate.sh +67 -0
  31. package/skills/ti-branding/scripts/ti-branding +462 -0
  32. package/skills/ti-expert/SKILL.md +1 -1
  33. package/skills/ti-guides/SKILL.md +1 -1
  34. package/skills/ti-howtos/SKILL.md +1 -1
  35. package/skills/ti-ui/SKILL.md +1 -1
package/bin/titools.js CHANGED
@@ -14,6 +14,7 @@ import { uninstallCommand } from '../lib/commands/uninstall.js';
14
14
  import { autoUpdateCommand } from '../lib/commands/auto-update.js';
15
15
  import { statusCommand } from '../lib/commands/status.js';
16
16
  import { doctorCommand } from '../lib/commands/doctor.js';
17
+ import { listCommand } from '../lib/commands/list.js';
17
18
 
18
19
  const program = new Command();
19
20
 
@@ -73,6 +74,13 @@ program
73
74
  .description('Check installation health and diagnose issues')
74
75
  .action(doctorCommand);
75
76
 
77
+ // List command
78
+ program
79
+ .command('list')
80
+ .alias('ls')
81
+ .description('List available Titanium skills with short descriptions')
82
+ .action(listCommand);
83
+
76
84
  // Parse arguments
77
85
  program.parse();
78
86
 
@@ -0,0 +1,105 @@
1
+ /**
2
+ * List command
3
+ * Enumerates available Titanium skills with a short description.
4
+ * Reads each skill's SKILL.md frontmatter — no hardcoded list.
5
+ */
6
+
7
+ import chalk from 'chalk';
8
+ import { existsSync, readFileSync } from 'fs';
9
+ import { join } from 'path';
10
+ import {
11
+ SKILLS,
12
+ PACKAGE_VERSION,
13
+ getAgentsSkillsDir,
14
+ } from '../config.js';
15
+
16
+ const CHECK = chalk.green('✓');
17
+ const CROSS = chalk.red('✗');
18
+
19
+ /**
20
+ * Extract the skill's human-readable name and short description from SKILL.md.
21
+ * Returns { description, installed } where description is the first sentence of
22
+ * the frontmatter description, trimmed for terminal display.
23
+ */
24
+ function readSkillMetadata(skillDir) {
25
+ const skillMd = join(skillDir, 'SKILL.md');
26
+ if (!existsSync(skillMd)) {
27
+ return { description: null, installed: false };
28
+ }
29
+
30
+ try {
31
+ const content = readFileSync(skillMd, 'utf8');
32
+ const frontmatter = content.match(/^---\n([\s\S]*?)\n---/);
33
+ if (!frontmatter) return { description: null, installed: true };
34
+
35
+ const descMatch = frontmatter[1].match(/description:\s*"([^"]+)"|description:\s*(.+)/);
36
+ if (!descMatch) return { description: null, installed: true };
37
+
38
+ const full = descMatch[1] || descMatch[2] || '';
39
+ // First sentence: period followed by whitespace (avoids breaking on "SDK 13."
40
+ // or other version-number periods). Falls back to a word-safe length cutoff.
41
+ let short;
42
+ const firstSentence = full.match(/^([^]*?\.)\s/);
43
+ if (firstSentence) {
44
+ short = firstSentence[1];
45
+ } else if (full.length > 80) {
46
+ const cut = full.slice(0, 80);
47
+ short = cut.slice(0, cut.lastIndexOf(' ')) + '…';
48
+ } else {
49
+ short = full;
50
+ }
51
+ return { description: short.trim(), installed: true };
52
+ } catch {
53
+ return { description: null, installed: true };
54
+ }
55
+ }
56
+
57
+ export async function listCommand() {
58
+ console.log('');
59
+ console.log(chalk.bold.blue(`Titanium skills (v${PACKAGE_VERSION})`));
60
+ console.log('');
61
+
62
+ const skillsDir = getAgentsSkillsDir();
63
+
64
+ if (!existsSync(skillsDir)) {
65
+ console.log(chalk.yellow('No skills installed yet.'));
66
+ console.log('Install with:');
67
+ console.log(chalk.cyan(' titools install'));
68
+ console.log('');
69
+ return;
70
+ }
71
+
72
+ const rows = [];
73
+ let installedCount = 0;
74
+ let maxNameLen = 0;
75
+
76
+ for (const name of SKILLS) {
77
+ const skillDir = join(skillsDir, name);
78
+ const { description, installed } = readSkillMetadata(skillDir);
79
+
80
+ if (installed) installedCount++;
81
+ if (name.length > maxNameLen) maxNameLen = name.length;
82
+
83
+ rows.push({ name, description, installed });
84
+ }
85
+
86
+ // Print aligned rows
87
+ for (const row of rows) {
88
+ const mark = row.installed ? CHECK : CROSS;
89
+ const paddedName = row.name.padEnd(maxNameLen + 2);
90
+ const desc = row.description
91
+ ? chalk.gray(row.description)
92
+ : chalk.gray(row.installed ? '(no description)' : 'not installed');
93
+
94
+ console.log(` ${mark} ${chalk.cyan(paddedName)} ${desc}`);
95
+ }
96
+
97
+ console.log('');
98
+ console.log(chalk.gray(`${installedCount}/${SKILLS.length} installed at ${skillsDir}`));
99
+ console.log('');
100
+ console.log(chalk.gray('Run `titools status` for installation health.'));
101
+ console.log(chalk.gray('Run `titools doctor` to diagnose issues.'));
102
+ console.log('');
103
+ }
104
+
105
+ export default listCommand;
package/lib/config.js CHANGED
@@ -38,6 +38,7 @@ export const SKILLS = [
38
38
  'ti-guides',
39
39
  'alloy-guides',
40
40
  'alloy-howtos',
41
+ 'ti-branding',
41
42
  ];
42
43
  // Legacy skills to remove during updates/uninstall
43
44
  export const LEGACY_SKILLS = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maccesar/titools",
3
- "version": "2.5.0",
3
+ "version": "2.6.0",
4
4
  "description": "Titanium SDK skills and agents for AI coding assistants (Claude Code, Gemini CLI, Codex CLI)",
5
5
  "main": "lib/index.js",
6
6
  "type": "module",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: alloy-guides
3
- description: "Titanium Alloy MVC official framework reference. Use when working with, reviewing, analyzing, or examining Alloy models, views, controllers, Backbone.js data binding, TSS styling, widgets, Alloy CLI, sync adapters, migrations, or MVC compilation. Explains how Backbone.js models and collections work in Alloy."
3
+ description: "Titanium Alloy MVC official framework reference. Use when working with, reviewing, analyzing, or examining Alloy models, views, controllers, Backbone.js data binding, TSS styling, widgets, Alloy CLI, sync adapters, migrations, or MVC compilation. AUTO-DETECT: If the project has an app/views/ + app/controllers/ + app/styles/ folder structure, it is an Alloy project — invoke this skill BEFORE editing XML views, JS controllers, or TSS styles. Alloy XML is NOT HTML; TSS is NOT CSS; controllers follow Alloy-specific patterns, not web MVC."
4
4
  argument-hint: "[concept]"
5
5
  allowed-tools: Read, Grep, Glob, Edit, Write, Bash(node *)
6
6
  ---
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: alloy-howtos
3
- description: "Titanium Alloy CLI and configuration guide. Use when creating, reviewing, analyzing, or examining Alloy projects, running alloy commands (new, generate, compile), configuring alloy.jmk or config.json, debugging compilation errors, creating conditional views, using Backbone.Events for communication, or writing custom XML tags."
3
+ description: "Titanium Alloy CLI and configuration guide. Use when creating, reviewing, analyzing, or examining Alloy projects, running alloy commands (new, generate, compile), configuring alloy.jmk or config.json, debugging compilation errors, creating conditional views, using Backbone.Events for communication, or writing custom XML tags. AUTO-DETECT: If the project has app/views/ + app/controllers/ structure and the task involves Alloy CLI commands, project configuration, or build issues, invoke this skill first."
4
4
  argument-hint: "[task]"
5
5
  allowed-tools: Read, Grep, Glob, Edit, Write, Bash(alloy *), Bash(node *)
6
6
  ---
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: purgetss
3
- description: "Titanium PurgeTSS utility-first styling toolkit. Use when styling, reviewing, analyzing, or examining Titanium UI with utility classes, configuring config.cjs, creating dynamic components with $.UI.create(), building animations, using grid layouts, setting up icon fonts, or working with TSS styles. Never suggest other CSS framework classes - verify in class-index.md first."
3
+ description: "Titanium PurgeTSS utility-first styling toolkit. Use when styling, reviewing, analyzing, or examining Titanium UI with utility classes, configuring config.cjs, creating dynamic components with $.UI.create(), building animations, using grid layouts, setting up icon fonts, or working with TSS styles. AUTO-DETECT: If purgetss/ folder or purgetss/config.cjs exists, this project uses PurgeTSS — invoke this skill BEFORE writing ANY styling code. All styling MUST use PurgeTSS utility classes in XML, NOT custom TSS. PurgeTSS classes look like Tailwind but are NOT Tailwind — verify every class exists before using it. Never use padding on Views (use margins on children), never use flexbox classes, never write manual TSS when a utility class exists."
4
4
  argument-hint: "[class-name]"
5
5
  allowed-tools: Read, Grep, Glob, Edit, Write, Bash(purgetss *), Bash(node *)
6
6
  ---
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: ti-api
3
- description: "Titanium SDK complete API reference. Use when looking up properties, methods, events, constants, or type signatures for any Ti.* or Modules.* API. Covers Ti.UI, Ti.Android, Ti.App, Ti.Media, Ti.Network, Ti.Database, Ti.Filesystem, Ti.Geolocation, Ti.Contacts, Ti.Calendar, Global, and third-party modules (Map, BLE, NFC, Facebook, Identity, CoreMotion)."
3
+ description: "Titanium SDK complete API reference. Use when looking up properties, methods, events, constants, or type signatures for any Ti.* or Modules.* API. Covers Ti.UI, Ti.Android, Ti.App, Ti.Media, Ti.Network, Ti.Database, Ti.Filesystem, Ti.Geolocation, Ti.Contacts, Ti.Calendar, Global, and third-party modules (Map, BLE, NFC, Facebook, Identity, CoreMotion). AUTO-DETECT: If tiapp.xml exists in the project, this is a Titanium project — invoke this skill BEFORE writing any code that uses Ti.* APIs. Do NOT rely on training data for Titanium APIs; always check the reference files in this skill first."
4
4
  argument-hint: "[Ti.UI.Window | Ti.Network.HTTPClient | Modules.Map.View | ...]"
5
5
  allowed-tools: Read, Grep, Glob
6
6
  ---
@@ -0,0 +1,225 @@
1
+ ---
2
+ name: ti-branding
3
+ description: "Generate complete app branding assets for modern Titanium SDK 13.x projects — launcher icons, adaptive icons, splash-screen icons, notification icons, and marketplace artwork — from a single SVG or PNG master. Use when the user asks to brand their app, update the app icon, set up splash screens, prepare store assets, fix generic/placeholder icons, add a notification icon, generate a launcher for Android 8+/13+, replace the TiTools default icon, or anything related to visual identity of a Titanium app (Alloy or Classic). Auto-detects Alloy vs Classic layout. Outputs iOS `DefaultIcon-ios.png` (flattened), Android adaptive triplet (foreground + background + monochrome) across 5 densities, Android legacy launcher × 5, marketplace artwork (1024² + 512²), and optionally notification icons and Android 12+ splash icons. Targets SDK 13.0–13.2 minimums without legacy cruft (post-Xcode 14 iOS minimums, no 9-patch splash, no pre-adaptive Android icons). Delegates raster work to ImageMagick + librsvg (system tools) — zero npm/pip dependencies. Invoke this skill whenever the user mentions icons, splash screens, branding, launcher, adaptive icon, mipmap, appiconset, DefaultIcon, iTunesConnect, Play Store artwork, or any visual asset for a Titanium app."
4
+ argument-hint: "[master-path] [--bg-color <hex>] [--padding <pct>] [--with-notification] [--with-splash-icon] [--cleanup-legacy] [--aggressive] [--dry-run]"
5
+ allowed-tools: Read, Glob, Bash, Write, Edit
6
+ ---
7
+
8
+ # Titanium branding — icons and splash screens
9
+
10
+ Generate the full set of launcher icons, adaptive icons, splash icons, notification icons, and marketplace artwork for a Titanium SDK 13.x project from ONE master input. Non-destructive by default (dry-run first, confirm before overwriting).
11
+
12
+ ## When to invoke this skill
13
+
14
+ Invoke proactively whenever the user's work touches any of:
15
+
16
+ - Replacing the generic/placeholder icon that ships with new Titanium projects
17
+ - Adding brand identity (logo-based launcher) to an app
18
+ - Fixing "my icon looks pixelated / pegado / cut-off on Android"
19
+ - Setting up the Android 12+ splash screen with a custom background color
20
+ - Generating notification icons for Firebase Cloud Messaging / local reminders
21
+ - Preparing App Store / Google Play artwork for a release build
22
+ - Updating icons after a rebrand or logo refresh
23
+ - Generating adaptive icon foreground / background / monochrome layers
24
+ - Migrating a legacy project to modern Android adaptive icons
25
+
26
+ ## What gets generated
27
+
28
+ Every invocation produces (in a staging directory, reviewed before copy):
29
+
30
+ | Asset | Path in project | Why |
31
+ |---|---|---|
32
+ | `DefaultIcon-ios.png` (1024×1024, no alpha) | Project root | iOS SDK generates the full appiconset from this at build time. Flattened because Apple rejects alpha channels. |
33
+ | `iTunesConnect.png` (1024×1024, no alpha) | Project root | App Store submission requirement. |
34
+ | `MarketplaceArtwork.png` (512×512, no alpha) | Project root | Google Play submission requirement. |
35
+ | `ic_launcher_foreground.png` × 5 densities | `app/platform/android/res/mipmap-{m,h,x,xx,xxx}hdpi/` | Adaptive icon foreground layer. Logo centered in 108dp canvas with configurable padding (default 22% ≈ 66dp safe-zone). |
36
+ | `ic_launcher_background.png` × 5 densities | idem | Adaptive icon background layer — solid `--bg-color`. |
37
+ | `ic_launcher_monochrome.png` × 5 densities | idem | Android 13+ themed icons (all non-transparent pixels → white). |
38
+ | `ic_launcher.png` × 5 densities (legacy) | idem | Fallback for Android < 8 (~3% of users in 2026). |
39
+ | `ic_launcher.xml` | `app/platform/android/res/mipmap-anydpi-v26/` | Adaptive icon definition that binds the 3 layers. |
40
+
41
+ Optional (flags):
42
+
43
+ | Asset | Flag | Path |
44
+ |---|---|---|
45
+ | `ic_stat_notify.png` × 5 densities (white + alpha) | `--with-notification` | `app/platform/android/res/drawable-{m,h,x,xx,xxx}hdpi/` |
46
+ | `splash_icon.png` × 5 densities | `--with-splash-icon` | idem (drawable-*) — for Android 12+ `windowSplashScreenAnimatedIcon` |
47
+
48
+ For Classic projects (Resources/ layout), paths resolve to `Resources/android/...` instead of `app/platform/android/...`.
49
+
50
+ ## Dependencies
51
+
52
+ - **ImageMagick 7.x** (required) — raster ops. `brew install imagemagick` / `apt install imagemagick`
53
+ - **librsvg** (optional, only if input is SVG) — SVG → PNG rasterization. `brew install librsvg` / `apt install librsvg2-bin`
54
+ - **Python 3** (optional, only for `--with-notification` alpha-mask extraction) — stdlib only, no pip install needed
55
+
56
+ The skill's `scripts/lib/deps.sh` detects missing tools and prints OS-specific install instructions. Do not attempt to auto-install.
57
+
58
+ ## Invocation
59
+
60
+ Main entry point: `scripts/ti-branding`. The skill runs it via Bash and then handles the review/copy workflow in Claude.
61
+
62
+ ```bash
63
+ bash scripts/ti-branding <master> [options]
64
+ ```
65
+
66
+ Options:
67
+
68
+ | Flag | Default | Purpose |
69
+ |---|---|---|
70
+ | `--bg-color <hex>` | `#FFFFFF` | Solid color for adaptive background layer. Also used for iOS alpha flatten. |
71
+ | `--padding <pct>` | `22` | Safe-zone padding per side (Android official minimum is 19.44% — 22% adds a small buffer against launcher masking). Range 0–40. |
72
+ | `--with-notification` | off | Emit `ic_stat_notify.png` × 5 densities. |
73
+ | `--with-splash-icon` | off | Emit `splash_icon.png` × 5 densities (Android 12+ SplashScreen API). |
74
+ | `--cleanup-legacy` | off | After generating (or standalone), scan the project for legacy branding artifacts — iOS launch image PNGs, Android `default.png`, `appicon.png`, `res-long-*/res-notlong-*`, etc. — and remove them. Context-aware: reads `tiapp.xml` to decide what's safe. See `references/cleanup-legacy.md`. |
75
+ | `--aggressive` | off | With `--cleanup-legacy`, also remove `ldpi` density folders (<1% of active devices globally in 2026). Off by default to be conservative. |
76
+ | `--output <dir>` | `<project>/.ti-branding/` | Staging directory. Review before copying to `app/`. |
77
+ | `--dry-run` | off | Print what would be generated/removed without writing or deleting. Works with both generation and `--cleanup-legacy`. |
78
+
79
+ ## Safety reminders
80
+
81
+ This skill writes PNGs and an XML file into the project's `app/platform/android/res/` and `app/assets/iphone/` paths, and with `--cleanup-legacy` it deletes obsolete branding artifacts. The flow is designed to be safe (staging → review → copy, dry-run first, `tiapp.xml`-driven safety rules), but the user should commit the project before running destructive operations so that `git restore` is available as a rollback. The tool is provided AS IS under the MIT License. No warranty, no liability — see the repository's `LICENSE`.
82
+
83
+ ## Workflow
84
+
85
+ 1. **Detect project layout** — look for `app/` (Alloy) or `Resources/` (Classic). If neither, error.
86
+ 2. **Validate master** — run `scripts/lib/validate.sh` to confirm dimensions ≥ 1024×1024, square, and check for alpha-bleed at edges.
87
+ 3. **Check dependencies** — `scripts/lib/deps.sh` verifies `magick` + (if SVG) `rsvg-convert`.
88
+ 4. **Prepare master** — `scripts/lib/prepare-master.sh` converts SVG → 1024×1024 PNG with transparency preserved, or normalizes PNG input. Auto-crops transparent padding already in the source.
89
+ 5. **Generate assets** — call `gen-ios.sh`, `gen-android-adaptive.sh`, `gen-android-legacy.sh`, `gen-marketplace.sh` (and optionally `gen-notification.sh`, `gen-splash-icon.sh`). All outputs land in the staging directory.
90
+ 6. **Review with user** — show a diff of what will be overwritten in the project. Ask for explicit confirmation.
91
+
92
+ When opening generated PNGs for visual review, use the OS-native **lightweight previewer** — not whatever app the user has configured as the default PNG handler. Otherwise heavy editors like Affinity, Photoshop, or GIMP launch for a simple 3-file preview, which is annoying. Commands by OS:
93
+
94
+ - **macOS**: `open -a Preview <file>...` — Preview.app ships with every Mac, lightweight, always available.
95
+ - **Linux**: `xdg-open <file>` — desktop-agnostic, honors the user's registered image viewer. If you need something specific, `eog` (GNOME) / `gwenview` (KDE) / `feh` are common lightweight viewers. Prefer `xdg-open` as the portable default.
96
+ - **Windows**: `start "" <file>` (cmd) or `Invoke-Item <file>` (PowerShell). Windows doesn't ship a universal lightweight viewer equivalent to Preview — it uses whatever the user set (Photos app by default on Windows 10/11). Live with that.
97
+
98
+ Only preview 2–3 representative assets (e.g. `DefaultIcon-ios.png`, the highest-density `ic_launcher_foreground.png`, and — if generated — `splash_icon.png`). Do not open all 20+ PNGs.
99
+ 7. **Copy to project** — after confirmation, copy staging → target paths. Keep the staging directory for rollback.
100
+ 8. **Print tiapp.xml snippets** — do NOT edit `tiapp.xml` automatically. Print exact XML blocks for the user to review and paste manually. See `references/tiapp-xml-snippets.md` for the blocks.
101
+ 9. **Suggest verification build** — `ti clean && ti build -p android -T emulator` / `-p ios -T simulator`.
102
+
103
+ ## Padding guidance (important)
104
+
105
+ The Android adaptive icon spec defines a 108dp canvas with a 66dp safe-zone. Expressed as padding: `(108-66)/2/108 ≈ 19.44%` per side. Anything inside the safe-zone is guaranteed to be visible regardless of the launcher's mask (circle, squircle, teardrop).
106
+
107
+ Defaults and recommendations:
108
+
109
+ | Padding | Logo fill | When to use |
110
+ |---|---|---|
111
+ | `19` (spec minimum) | 62% | Intricate logos needing maximum visible detail. Risky — leaves no buffer for aggressive launcher masks. |
112
+ | `22` (default) | 56% | Balanced: compliant with spec + 3% buffer. Recommended for most apps. |
113
+ | `25` | 50% | Logos with fine details near edges (wordmarks, thin strokes). |
114
+ | `28`–`32` | 44%–36% | Simple icons, single-letter monograms, bold shapes. Gives visual breathing room. |
115
+
116
+ If the user reports "my logo looks pegado / cramped / cut off on edges", increase padding. If the user reports "my logo looks tiny / lost in the middle", decrease padding.
117
+
118
+ ## iOS notes (modern)
119
+
120
+ - iOS 13+ only. Targets Titanium SDK 13.0+.
121
+ - `DefaultIcon-ios.png` is 1024×1024 with **no alpha channel** — Apple rejects transparency. The skill flattens alpha over `--bg-color`.
122
+ - Xcode 14+ no longer requires the full 20-size appiconset. Titanium generates all required sizes from `DefaultIcon-ios.png` at build time into `build/iphone/Assets.xcassets/AppIcon.appiconset/` — the source project only needs the master.
123
+ - `DefaultIcon-Dark.png` and `DefaultIcon-Tinted.png` (iOS 18+) are out of scope for this skill's v1. The user can add them manually later.
124
+ - Launch images (`Default-*@3x.png`) are intentionally NOT generated. Modern Titanium uses `<enable-launch-screen-storyboard>true</enable-launch-screen-storyboard>` which adapts to any resolution via the storyboard + `<default-background-color>`. Legacy PNG launch images are dead weight.
125
+
126
+ See `references/ios-appiconset.md` for full details.
127
+
128
+ ## Android notes (modern)
129
+
130
+ - Minimum API: 21 (Lollipop). Target: API 34 (Android 14).
131
+ - Adaptive icons (API 26+) are the primary launcher icon. Legacy `ic_launcher.png` (flat) is included only as fallback for API 21–25.
132
+ - Monochrome layer (API 31+) is required for themed icons. The skill generates it by tinting all non-transparent foreground pixels to pure white (`RGB 255,255,255`, alpha preserved).
133
+ - Splash screen (API 31+) uses `windowSplashScreenBackground` + `windowSplashScreenAnimatedIcon` in the app theme. Pre-12 Android falls back to the launcher icon automatically. 9-patch `background.9.png` is obsolete — not generated.
134
+ - Notification icons (if `--with-notification`) must be white-on-transparent. Android applies a tint at runtime based on the notification's `color` property.
135
+
136
+ See `references/android-adaptive-icons.md` and `references/splash-screen-api.md` for depth.
137
+
138
+ ## Reference files
139
+
140
+ Load these on-demand when implementing specific parts of the workflow:
141
+
142
+ - `references/ti-icon-paths.md` — Canonical paths for Alloy vs Classic layouts, per Titanium SDK version.
143
+ - `references/android-adaptive-icons.md` — Safe-zone math, densities, XML bind format, monochrome rules.
144
+ - `references/ios-appiconset.md` — Xcode 14+ minimums, DefaultIcon pipeline, alpha flattening.
145
+ - `references/notification-icons.md` — White-only rule, runtime tinting, size table.
146
+ - `references/splash-screen-api.md` — Android 12+ SplashScreen vs pre-12 legacy, iOS storyboard.
147
+ - `references/master-input-guidelines.md` — SVG best practices, PNG alpha handling, bbox auto-detection, padding ergonomics.
148
+ - `references/tiapp-xml-snippets.md` — Copy-paste blocks for `<default-background-color>`, splash theme overrides, adaptive icon manifest entries.
149
+ - `references/cleanup-legacy.md` — What `--cleanup-legacy` removes, why each artifact is obsolete, the `tiapp.xml`-driven safety rules, and real-world space savings from dogfooding on SNAP Gym.
150
+
151
+ ## Non-goals
152
+
153
+ - Does not generate iOS launch image PNGs (`Default-*@3x.png`) — storyboard-driven, no longer needed.
154
+ - Does not generate Android `background.9.png` 9-patch splash — obsolete since Ti SDK 10+.
155
+ - Does not edit `tiapp.xml` — prints snippets only. User decides what to paste.
156
+ - **Does not create `values-v31/splash_theme.xml`, `values/colors.xml`, or any other resource XML file that depends on project-specific config (Gradle dependencies, existing themes, etc.).** Prints snippets for the user to paste after review. The only XML file the skill does write is `mipmap-anydpi-v26/ic_launcher.xml` — that one is pure adaptive-icon binding with no external library requirements.
157
+ - Does not install ImageMagick or librsvg — detects and instructs.
158
+ - Does not handle `DefaultIcon-Dark.png` / `DefaultIcon-Tinted.png` in v1. Leave for a future flag if users request it.
159
+ - Does not handle tab bar / toolbar icons. Those are in-app assets, not branding.
160
+
161
+ ## Known limitations
162
+
163
+ ### `--with-splash-icon` is "PNG-only" — wire-up is user's responsibility
164
+
165
+ Titanium SDK 13.x already generates a reasonable Android 12+ splash screen automatically, using the launcher icon you just created plus the `<default-background-color>` from `tiapp.xml`. For most apps this default is good enough and requires zero extra configuration.
166
+
167
+ The `--with-splash-icon` flag generates `splash_icon.png × 5 densities` for advanced users who want a splash icon visually distinct from the launcher icon. Wiring it up requires a custom theme, which has TWO flavors (both printed in the post-generation notes):
168
+
169
+ - **Native platform theme** (API 31+ only, no library): uses `parent="@android:style/Theme.DeviceDefault.NoActionBar"` with `android:windowSplashScreen*` attributes. Compiles out of the box. Pre-12 devices fall back to Titanium's default splash.
170
+ - **androidx.core:core-splashscreen library** (API 21+ backward-compat): uses `parent="Theme.SplashScreen"` with unqualified attributes. Requires adding `implementation 'androidx.core:core-splashscreen:1.0.1'` to `app/platform/android/build.gradle`.
171
+
172
+ The skill does NOT auto-pick or auto-create these resource files because:
173
+ 1. The user may already have custom themes that conflict
174
+ 2. The library flavor requires modifying Gradle config (can't be reversed cleanly)
175
+ 3. `tiapp.xml` meta-data registration requires opening a possibly self-closing `<application>` tag
176
+
177
+ Print both options, explain the tradeoffs, let the user decide.
178
+
179
+ ### Do NOT set the splash theme on `<application android:theme>` or on any `<activity>`
180
+
181
+ Tempting but wrong. Titanium's `Theme.AppDerived` inherits from the `<application>` theme. Setting a NoActionBar splash theme there propagates NoActionBar to every `TiActivity` in the app, stripping the ActionBar / TitleBar from every screen globally. The only correct registration is via `<meta-data android:name="io.tidev.titanium.splash.theme">`.
182
+
183
+ ### `<application>` in `tiapp.xml` may be self-closing
184
+
185
+ When the project's `<application>` tag is self-closing (e.g. `<application android:icon="@mipmap/ic_launcher"/>`), users must expand it before adding `<meta-data>` children:
186
+
187
+ ```xml
188
+ <!-- Before (self-closing) -->
189
+ <application android:icon="@mipmap/ic_launcher"/>
190
+
191
+ <!-- After (expanded) -->
192
+ <application android:icon="@mipmap/ic_launcher">
193
+ <meta-data .../>
194
+ </application>
195
+ ```
196
+
197
+ The skill's post-generation notes remind the user of this.
198
+
199
+ ## Example invocations
200
+
201
+ ```bash
202
+ # Minimal: PNG master, white background, default 22% padding
203
+ bash scripts/ti-branding ./logo.png
204
+
205
+ # SNAP Gym full kit: SVG master, navy background, notification + splash
206
+ bash scripts/ti-branding ./docs/snap-logo.svg \
207
+ --bg-color "#0B1326" \
208
+ --padding 22 \
209
+ --with-notification \
210
+ --with-splash-icon
211
+
212
+ # Tight padding for a detailed wordmark
213
+ bash scripts/ti-branding ./logo.svg --padding 19 --bg-color "#000000"
214
+
215
+ # Preview only (no files written)
216
+ bash scripts/ti-branding ./logo.svg --bg-color "#FF6600" --dry-run
217
+
218
+ # Cleanup-only mode — no master image needed, removes legacy artifacts
219
+ bash scripts/ti-branding --cleanup-legacy --dry-run
220
+ bash scripts/ti-branding --cleanup-legacy # apply
221
+ bash scripts/ti-branding --cleanup-legacy --aggressive # also ldpi
222
+
223
+ # One-shot: generate branding AND clean up legacy in a single invocation
224
+ bash scripts/ti-branding ./logo.svg --bg-color "#0B1326" --cleanup-legacy
225
+ ```
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
3
+ <background android:drawable="@mipmap/ic_launcher_background"/>
4
+ <foreground android:drawable="@mipmap/ic_launcher_foreground"/>
5
+ <monochrome android:drawable="@mipmap/ic_launcher_monochrome"/>
6
+ </adaptive-icon>
@@ -0,0 +1,85 @@
1
+ # Android adaptive icons (API 26+)
2
+
3
+ ## Canvas and safe-zone
4
+
5
+ Adaptive icons use a fixed 108×108 dp virtual canvas composed of two layers:
6
+
7
+ - **Foreground**: the logo/glyph with transparency outside the safe-zone
8
+ - **Background**: solid color, gradient, or pattern filling the full canvas
9
+
10
+ The OS launcher applies a mask (circle, squircle, teardrop, rounded square — up to the OEM) and clips both layers to that shape. Only the central **66×66 dp safe-zone** is guaranteed to remain visible regardless of the mask.
11
+
12
+ Translation to padding:
13
+
14
+ ```
15
+ safe-zone: 66 / 108 = 61.1% of canvas
16
+ min padding: (108 - 66) / 2 / 108 = 19.44% per side
17
+ ```
18
+
19
+ Anything beyond 66dp toward the edge is at the launcher's discretion — some masks (circle) hide more, some (squircle) hide less.
20
+
21
+ ## Density sizes
22
+
23
+ One pixel unit equals `density_scale × 1 dp`:
24
+
25
+ | Density | Scale | Canvas size (108 dp) |
26
+ |----------|-------|----------------------|
27
+ | mdpi | 1.0× | 108 px |
28
+ | hdpi | 1.5× | 162 px |
29
+ | xhdpi | 2.0× | 216 px |
30
+ | xxhdpi | 3.0× | 324 px |
31
+ | xxxhdpi | 4.0× | 432 px |
32
+
33
+ Ship all five. The OS picks the closest match for the user's screen density.
34
+
35
+ ## Monochrome layer (API 31+)
36
+
37
+ Android 13 introduced themed icons: the user can tell the launcher to re-color all app icons with the system accent color. The OS uses the `monochrome` drawable for this treatment.
38
+
39
+ Rules for the monochrome drawable:
40
+
41
+ - All non-transparent pixels become pure white at build time — the OS tint replaces white with the theme color at render time
42
+ - Alpha channel must be preserved (same silhouette as foreground, transparency intact)
43
+ - Do NOT include color information — it will be discarded
44
+
45
+ The skill generates monochrome by taking the foreground and running ImageMagick's `-channel RGB -fill white -colorize 100 +channel` which replaces RGB with white while leaving the alpha untouched.
46
+
47
+ ## XML bind
48
+
49
+ One file ties the three layers together. Ships to `mipmap-anydpi-v26/ic_launcher.xml`:
50
+
51
+ ```xml
52
+ <?xml version="1.0" encoding="utf-8"?>
53
+ <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
54
+ <background android:drawable="@mipmap/ic_launcher_background"/>
55
+ <foreground android:drawable="@mipmap/ic_launcher_foreground"/>
56
+ <monochrome android:drawable="@mipmap/ic_launcher_monochrome"/>
57
+ </adaptive-icon>
58
+ ```
59
+
60
+ The `v26` qualifier ensures only API 26+ devices use this file. Older devices fall through to the legacy `mipmap-*/ic_launcher.png` flat drawable.
61
+
62
+ ## Legacy flat icon
63
+
64
+ For API 21–25 (~3% of active users in 2026) the launcher still uses a flat PNG:
65
+
66
+ | Density | Size |
67
+ |----------|------|
68
+ | mdpi | 48 |
69
+ | hdpi | 72 |
70
+ | xhdpi | 96 |
71
+ | xxhdpi | 144 |
72
+ | xxxhdpi | 192 |
73
+
74
+ Fill more of the canvas here — legacy launchers don't apply adaptive masking. The skill reduces the padding by 40% for this composite.
75
+
76
+ ## Verifying
77
+
78
+ - Android Studio has a Resource Manager that previews adaptive icons with multiple masks. Point it at `app/platform/android/res/` to inspect.
79
+ - On a device/emulator running API 26+, long-press the launcher icon and the animated wiggle reveals whether the adaptive layers are wired correctly.
80
+ - On API 31+, toggle "Themed icons" in the launcher settings to verify the monochrome layer.
81
+
82
+ ## References
83
+
84
+ - Android Developer: [Adaptive icons](https://developer.android.com/develop/ui/views/launch/icon_design_adaptive)
85
+ - Android Developer: [Themed app icons](https://developer.android.com/about/versions/13/features#themed-app-icons)
@@ -0,0 +1,112 @@
1
+ # `--cleanup-legacy` — removing obsolete branding artifacts
2
+
3
+ Titanium project templates ship with a lot of legacy branding assets that made sense a decade ago and are dead weight today. The `--cleanup-legacy` flag scans the project and removes them, but only after verifying through `tiapp.xml` that they are genuinely unused.
4
+
5
+ ## Why cleanup matters
6
+
7
+ Legacy branding assets bloat the project in three ways:
8
+
9
+ 1. **Repository size** — every `Default-XXXh@3x.png` (some 800 KB+ each) stays in git history forever unless actively deleted.
10
+ 2. **Build output size** — some legacy assets DO get copied into the APK/IPA even when modern alternatives make them unreachable at runtime. Extra MB mean slower downloads for end users and marginally longer store review times.
11
+ 3. **Cognitive load** — new contributors look at `res-long-port-hdpi/`, `Default-Landscape-2688h@3x.png`, `background.9.png`, and reasonably assume they matter. They don't, but nobody is willing to delete what they don't fully understand.
12
+
13
+ ## The three buckets
14
+
15
+ The cleanup logic categorizes targets by how safe removal is:
16
+
17
+ ### SAFE — universally obsolete
18
+
19
+ Removed without checking any project configuration. These artifacts are fossils from Android versions predating the current SDK's minimum target.
20
+
21
+ | Artifact | Why it's dead |
22
+ |---|---|
23
+ | `app/assets/android/images/res-long-*/` | Android's `long` screen qualifier distinguished devices like the Motorola Droid (854×480) from the Nexus One (800×480) in 2009–2011. Since Android 3.0 the system uses dp-based layouts instead. No modern launcher or OS consults these folders. |
24
+ | `app/assets/android/images/res-notlong-*/` | Inverse of `long` — same verdict. |
25
+
26
+ These buckets are almost always empty in practice (Titanium templates create the folders but rarely populate them), so the cleanup is primarily about removing visual noise from the project tree.
27
+
28
+ ### CONDITIONAL — safe given the project's current configuration
29
+
30
+ Removed only when `tiapp.xml` confirms the artifact is genuinely unused.
31
+
32
+ | Artifact | Safety rule | Why |
33
+ |---|---|---|
34
+ | `app/assets/iphone/Default-*.png`, `Default@2x.png` | `<enable-launch-screen-storyboard>true</enable-launch-screen-storyboard>` | With the storyboard active, iOS adapts dynamically to any device resolution via Auto Layout. Apple mandated this in 2020. Without storyboard, these PNGs matter and must stay. |
35
+ | `app/assets/android/images/res-*-land-*/`, `res-land-*/` | `tiapp.xml` declares portrait-only orientations | Landscape variants only load when the app can rotate to landscape. |
36
+ | `app/assets/android/default.png` | `mipmap-anydpi-v26/ic_launcher.xml` exists (adaptive icons present) | The legacy Titanium Android splash PNG is shadowed by the modern SplashScreen API, which derives the splash from the launcher icon. Only deleted when the modern path is in place. |
37
+ | `app/assets/android/appicon.png` | Same adaptive-icons condition | Legacy Android launcher PNG. When adaptive icons exist in `mipmap-*/`, this file is redundant. |
38
+
39
+ If a safety rule is not satisfied, the artifact is preserved and the user sees a clear reason in the cleanup plan.
40
+
41
+ ### AGGRESSIVE — opt-in via `--aggressive`
42
+
43
+ Defensible but off by default because there are edge cases.
44
+
45
+ | Artifact | Reason it's usually safe |
46
+ |---|---|
47
+ | `app/assets/android/images/res-ldpi/`, `res-*-ldpi/` | ldpi (≤120 dpi, pre-2010 low-end devices) is below 1% of active Android devices globally. |
48
+ | `app/platform/android/res/drawable-ldpi/`, `mipmap-ldpi/`, `values-ldpi/` | Same ldpi justification for platform-native resources. |
49
+
50
+ Users targeting specific low-density markets (some IoT devices, kiosks) should leave `--aggressive` off.
51
+
52
+ ## Safety model
53
+
54
+ The flag is opinionated about not trashing anybody's work:
55
+
56
+ - `--dry-run` prints the full plan (paths, sizes, reasons) without deleting anything. Run it first.
57
+ - The plan always shows which `tiapp.xml` flags drove each decision (storyboard on/off, orientation, adaptive-icons presence) so the user can verify the detection is correct.
58
+ - The skill does not delete files outside the project's asset and platform resource directories.
59
+ - It does not touch `tiapp.xml`, source code, `modules/`, `i18n/`, or any application code.
60
+ - Conditional targets still require the safety rule to pass — even with `--cleanup-legacy`, nothing conditional deletes unless `tiapp.xml` justifies it.
61
+ - Aggressive-bucket targets require the explicit `--aggressive` flag on top of `--cleanup-legacy`.
62
+
63
+ ## Real-world savings
64
+
65
+ Measured on SNAP Gym, a mid-sized Titanium 13.1 Alloy project, immediately after a fresh `alloy new` template:
66
+
67
+ | Bucket | Items removed | Disk freed |
68
+ |---|---|---|
69
+ | SAFE (`res-long-*` + `res-notlong-*`) | 11 folders | ~0 KB (empty templates) |
70
+ | CONDITIONAL (`iphone/Default-*.png` × 15) | 15 files | ~5.4 MB |
71
+ | CONDITIONAL (`android/default.png`, `appicon.png`) | 2 files | 52 KB |
72
+ | **Total (default flags)** | **28 artifacts** | **~5.5 MB** |
73
+
74
+ Running `--aggressive` on top would remove an additional ~40 KB of `ldpi` folders — small payoff per project, but compounds when applied across multiple apps.
75
+
76
+ The 5.4 MB of iOS launch images is the largest single win: those PNGs exist in source but are not shipped in modern IPAs (storyboard-driven iOS builds ignore them). Removing them from source shrinks the repo and clears confusion for new contributors.
77
+
78
+ ## When NOT to run cleanup
79
+
80
+ - **Classic Titanium apps pre-SDK 10**: rely on the legacy assets. Upgrading the SDK is a prerequisite to safely cleaning up.
81
+ - **Apps with `<enable-launch-screen-storyboard>false</enable-launch-screen-storyboard>`**: the iOS PNGs are still consulted — the skill correctly skips them, but the user should enable the storyboard before running cleanup to get the savings.
82
+ - **Apps that support landscape orientation**: the `res-*-land-*` folders are preserved, which is correct.
83
+
84
+ ## Usage
85
+
86
+ ```bash
87
+ # Preview first — nothing deletes in dry-run mode
88
+ bash scripts/ti-branding --cleanup-legacy --dry-run
89
+
90
+ # Apply
91
+ bash scripts/ti-branding --cleanup-legacy
92
+
93
+ # Include ldpi
94
+ bash scripts/ti-branding --cleanup-legacy --aggressive
95
+
96
+ # Point at a specific project (default: current directory)
97
+ bash scripts/ti-branding --cleanup-legacy --project /path/to/project
98
+
99
+ # Combine with generation — brand the app and clean up in one pass
100
+ bash scripts/ti-branding ./logo.svg --bg-color "#0B1326" --cleanup-legacy
101
+ ```
102
+
103
+ ## Verification checklist
104
+
105
+ After applying cleanup, rebuild for each platform and visually confirm:
106
+
107
+ - [ ] iOS app on a modern device (iPhone 11 or newer): splash reaches top and bottom (no letterboxing). The storyboard is doing its job; the deleted PNGs are confirmed unused.
108
+ - [ ] Android app on API 31+ (Android 12 or newer): splash shows the launcher icon centered on the brand color, then transitions to the app normally.
109
+ - [ ] Android app on API 21–30 if the minimum target is that low: app launches without the old `default.png`. Titanium's adaptive-icon fallback kicks in.
110
+ - [ ] `git status` lists only the expected deletions. No source code changes.
111
+
112
+ If any of those fail, the deletion can be reverted with `git checkout -- .` (before committing) or `git restore` (after).