diff --git a/Assets/AppIcon.icon/Assets/01-rear-blue.svg b/Assets/AppIcon.icon/Assets/01-rear-blue.svg
new file mode 100644
index 0000000..a131890
--- /dev/null
+++ b/Assets/AppIcon.icon/Assets/01-rear-blue.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/Assets/AppIcon.icon/Assets/02-rear-teal.svg b/Assets/AppIcon.icon/Assets/02-rear-teal.svg
new file mode 100644
index 0000000..24490d0
--- /dev/null
+++ b/Assets/AppIcon.icon/Assets/02-rear-teal.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/Assets/AppIcon.icon/Assets/03-front-folder.svg b/Assets/AppIcon.icon/Assets/03-front-folder.svg
new file mode 100644
index 0000000..c2447a7
--- /dev/null
+++ b/Assets/AppIcon.icon/Assets/03-front-folder.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/Assets/AppIcon.icon/Assets/04-git-mark.svg b/Assets/AppIcon.icon/Assets/04-git-mark.svg
new file mode 100644
index 0000000..af4c34c
--- /dev/null
+++ b/Assets/AppIcon.icon/Assets/04-git-mark.svg
@@ -0,0 +1,9 @@
+
\ No newline at end of file
diff --git a/Assets/AppIcon.icon/Assets/05-branch-orange.svg b/Assets/AppIcon.icon/Assets/05-branch-orange.svg
new file mode 100644
index 0000000..377a54d
--- /dev/null
+++ b/Assets/AppIcon.icon/Assets/05-branch-orange.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/Assets/AppIcon.icon/Assets/06-branch-blue.svg b/Assets/AppIcon.icon/Assets/06-branch-blue.svg
new file mode 100644
index 0000000..00e597c
--- /dev/null
+++ b/Assets/AppIcon.icon/Assets/06-branch-blue.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/Assets/AppIcon.icon/Assets/07-branch-teal.svg b/Assets/AppIcon.icon/Assets/07-branch-teal.svg
new file mode 100644
index 0000000..f7d4dad
--- /dev/null
+++ b/Assets/AppIcon.icon/Assets/07-branch-teal.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/Assets/AppIcon.icon/Assets/08-branch-base.svg b/Assets/AppIcon.icon/Assets/08-branch-base.svg
new file mode 100644
index 0000000..3d1edfd
--- /dev/null
+++ b/Assets/AppIcon.icon/Assets/08-branch-base.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/Assets/AppIcon.icon/icon.json b/Assets/AppIcon.icon/icon.json
new file mode 100644
index 0000000..8df00c3
--- /dev/null
+++ b/Assets/AppIcon.icon/icon.json
@@ -0,0 +1,106 @@
+{
+ "fill-specializations" : [
+ {
+ "value" : {
+ "linear-gradient" : [
+ "display-p3:0.05490,0.14118,0.38824,1.00000",
+ "extended-srgb:0.00000,0.53333,1.00000,1.00000"
+ ]
+ }
+ },
+ {
+ "appearance" : "dark",
+ "value" : {
+ "linear-gradient" : [
+ "extended-gray:0.00000,1.00000",
+ "display-p3:0.05490,0.14118,0.38824,1.00000"
+ ]
+ }
+ }
+ ],
+ "groups" : [
+ {
+ "layers" : [
+ {
+ "image-name" : "08-branch-base.svg",
+ "name" : "08-branch-base"
+ },
+ {
+ "image-name" : "07-branch-teal.svg",
+ "name" : "07-branch-teal"
+ },
+ {
+ "image-name" : "06-branch-blue.svg",
+ "name" : "06-branch-blue"
+ },
+ {
+ "image-name" : "05-branch-orange.svg",
+ "name" : "05-branch-orange"
+ }
+ ],
+ "name" : "03 Worktree Branches",
+ "shadow" : {
+ "kind" : "layer-color",
+ "opacity" : 0.35
+ },
+ "translucency" : {
+ "enabled" : true,
+ "value" : 0.05
+ }
+ },
+ {
+ "layers" : [
+ {
+ "image-name" : "04-git-mark.svg",
+ "name" : "04-git-mark"
+ },
+ {
+ "image-name" : "03-front-folder.svg",
+ "name" : "03-front-folder"
+ }
+ ],
+ "lighting" : "combined",
+ "name" : "02 Repository",
+ "shadow" : {
+ "kind" : "neutral",
+ "opacity" : 0.5
+ },
+ "translucency" : {
+ "enabled" : true,
+ "value" : 0.1
+ }
+ },
+ {
+ "layers" : [
+ {
+ "image-name" : "02-rear-teal.svg",
+ "name" : "02-rear-teal"
+ },
+ {
+ "image-name" : "01-rear-blue.svg",
+ "name" : "01-rear-blue"
+ }
+ ],
+ "name" : "01 Rear Worktrees",
+ "refractivity" : {
+ "depth" : 0,
+ "enabled" : false,
+ "strength" : 0.5
+ },
+ "shadow" : {
+ "kind" : "layer-color",
+ "opacity" : 0.35
+ },
+ "translucency" : {
+ "enabled" : true,
+ "value" : 0.15
+ }
+ }
+ ],
+ "supported-platforms" : {
+ "circles" : [
+ "watchOS"
+ ],
+ "squares" : "shared"
+ }
+}
\ No newline at end of file
diff --git a/README.md b/README.md
index ee4f15e..f7335cc 100644
--- a/README.md
+++ b/README.md
@@ -42,6 +42,9 @@ globstar script, since macOS ships bash 3.2. `timber repo add` here has no
and whitened so both render as monochrome template images).
- `Sources/TimberModel/TimberModel.swift` — pure filter/argv logic ported
from `TimberModel.js`, UI-independent.
+- `Assets/AppIcon.icon/` — Icon Composer source for the app icon;
+ `mise run build` compiles it to `Assets.car` via `actool`, and
+ `CFBundleIconName` in `packaging/Info.plist` points at it.
- `Tests/TimberModelTests/` — unit tests for the model.
## Build & run
diff --git a/mise.toml b/mise.toml
index da566b1..51d1f47 100644
--- a/mise.toml
+++ b/mise.toml
@@ -36,6 +36,14 @@ mkdir -p dist/Timber.app/Contents/MacOS dist/Timber.app/Contents/Resources
lipo -create "$ARM_BIN/Timber" "$X86_BIN/Timber" -output dist/Timber.app/Contents/MacOS/Timber
cp packaging/Info.plist dist/Timber.app/Contents/Info.plist
cp -R "$ARM_BIN/Timber_Timber.bundle" dist/Timber.app/Contents/Resources/
+# Compile the Icon Composer source into Assets.car so the bundle gets a
+# real app icon (CFBundleIconName in Info.plist points at it). actool
+# exits nonzero on failure, and set -e stops the build there; its plist
+# report goes to a log so success stays quiet.
+ACTOOL_OUT="$(mktemp -d /tmp/timber-assets.XXXXXX)"
+xcrun actool --compile "$ACTOOL_OUT" --platform macosx --minimum-deployment-target 14.0 Assets/AppIcon.icon > "$ACTOOL_OUT/actool.log"
+cp "$ACTOOL_OUT"/Assets.car dist/Timber.app/Contents/Resources/
+rm -rf "$ACTOOL_OUT"
# Ad-hoc sign so Gatekeeper treats a downloaded copy as an intact app
# bundle instead of reporting it as damaged. Still unsigned for
# Gatekeeper's notarization check, so first launch needs right-click Open.
diff --git a/packaging/Info.plist b/packaging/Info.plist
index 35932e9..f059724 100644
--- a/packaging/Info.plist
+++ b/packaging/Info.plist
@@ -8,6 +8,8 @@
Timber
CFBundleExecutable
Timber
+ CFBundleIconName
+ AppIcon
CFBundlePackageType
APPL
CFBundleShortVersionString